From eef5de613c75661e5d94baa086f6f2ddc26c7ed0 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 24 Mar 2016 23:16:07 -0400 Subject: Added verb frames In addition: - Added prepositions. - Rewrote a lot of the query interface. It now, for a lot of relationships, supports nested AND, OR, and NOT logic. - Rewrote the token class. It is now a union-like class instead of being polymorphic, which means smart pointers are no longer necessary. - Querying with regards to word derivation has been temporarily removed. - Sentinel values are now supported for all word types. - The VerbNet data retrieved from http://verbs.colorado.edu/~mpalmer/projects/verbnet/downloads.html was found to not be perfectly satisfactory in some regards, especially regarding adjective phrases. A patch file is now included in the repository describing the changes made to the VerbNet v3.2 download for the canonical verbly datafile. --- lib/adjective.cpp | 655 ++------------------- lib/adjective.h | 94 +-- lib/adjective_query.cpp | 819 ++++++++++++++++++++++++++ lib/adjective_query.h | 91 +++ lib/adverb.cpp | 443 +-------------- lib/adverb.h | 62 +- lib/adverb_query.cpp | 514 +++++++++++++++++ lib/adverb_query.h | 65 +++ lib/c++14.h | 35 -- lib/data.cpp | 12 +- lib/data.h | 299 +++++++++- lib/frame.cpp | 320 +++++++++++ lib/frame.h | 118 ++++ lib/frame_query.cpp | 142 +++++ lib/frame_query.h | 21 + lib/noun.cpp | 1010 +++----------------------------- lib/noun.h | 150 +---- lib/noun_query.cpp | 1453 +++++++++++++++++++++++++++++++++++++++++++++++ lib/noun_query.h | 139 +++++ lib/preposition.cpp | 83 +++ lib/preposition.h | 38 ++ lib/token.cpp | 617 +++++++++++++++++++- lib/token.h | 413 +++++--------- lib/util.h | 8 +- lib/verb.cpp | 169 +----- lib/verb.h | 45 +- lib/verb_query.cpp | 170 ++++++ lib/verb_query.h | 34 ++ lib/verbly.h | 25 +- lib/word.cpp | 11 +- lib/word.h | 13 +- 31 files changed, 5241 insertions(+), 2827 deletions(-) create mode 100644 lib/adjective_query.cpp create mode 100644 lib/adjective_query.h create mode 100644 lib/adverb_query.cpp create mode 100644 lib/adverb_query.h delete mode 100644 lib/c++14.h create mode 100644 lib/frame.cpp create mode 100644 lib/frame.h create mode 100644 lib/frame_query.cpp create mode 100644 lib/frame_query.h create mode 100644 lib/noun_query.cpp create mode 100644 lib/noun_query.h create mode 100644 lib/preposition.cpp create mode 100644 lib/preposition.h create mode 100644 lib/verb_query.cpp create mode 100644 lib/verb_query.h (limited to 'lib') diff --git a/lib/adjective.cpp b/lib/adjective.cpp index b2b53e4..ba8254a 100644 --- a/lib/adjective.cpp +++ b/lib/adjective.cpp @@ -2,6 +2,11 @@ namespace verbly { + adjective::adjective() + { + + } + adjective::adjective(const data& _data, int _id) : word(_data, _id) { @@ -9,682 +14,100 @@ namespace verbly { std::string adjective::base_form() const { + assert(_valid == true); + return _base_form; } std::string adjective::comparative_form() const { + assert(_valid == true); + return _comparative_form; } std::string adjective::superlative_form() const { + assert(_valid == true); + return _superlative_form; } adjective::positioning adjective::position() const { + assert(_valid == true); + return _position; } bool adjective::has_comparative_form() const { + assert(_valid == true); + return !_comparative_form.empty(); } bool adjective::has_superlative_form() const { + assert(_valid == true); + return !_superlative_form.empty(); } bool adjective::has_position() const { + assert(_valid == true); + 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); + assert(_valid == true); - return *this; + return _data->adjectives().antonym_of(*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) + adjective_query adjective::synonyms() const { - _pertainym_of.push_back(_noun); + assert(_valid == true); - return *this; + return _data->adjectives().synonym_of(*this); } - adjective_query& adjective_query::is_mannernymic(bool _is_mannernymic) + adjective_query adjective::generalizations() const { - this->_is_mannernymic = _is_mannernymic; + assert(_valid == true); - return *this; + return _data->adjectives().generalization_of(*this); } - adjective_query& adjective_query::anti_mannernym_of(const adverb& _adv) + adjective_query adjective::specifications() const { - _anti_mannernym_of.push_back(_adv); + assert(_valid == true); - return *this; + return _data->adjectives().specification_of(*this); } - adjective_query& adjective_query::derived_from(const word& _w) + noun_query adjective::anti_pertainyms() const { - 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)); - } + assert(_valid == true); - return *this; + return _data->nouns().anti_pertainym_of(*this); } - adjective_query& adjective_query::not_derived_from(const word& _w) + adverb_query adjective::mannernyms() const { - 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)); - } + assert(_valid == true); - return *this; + return _data->adverbs().mannernym_of(*this); } - std::list adjective_query::run() const + noun_query adjective::attributes() 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); - } + assert(_valid == true); - 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; + return _data->nouns().attribute_of(*this); } }; diff --git a/lib/adjective.h b/lib/adjective.h index 3dcab9b..a6eb293 100644 --- a/lib/adjective.h +++ b/lib/adjective.h @@ -25,6 +25,7 @@ namespace verbly { friend class adjective_query; public: + adjective(); adjective(const data& _data, int _id); std::string base_form() const; @@ -45,99 +46,6 @@ namespace verbly { 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/adjective_query.cpp b/lib/adjective_query.cpp new file mode 100644 index 0000000..ec100e3 --- /dev/null +++ b/lib/adjective_query.cpp @@ -0,0 +1,819 @@ +#include "verbly.h" + +namespace verbly { + + 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() + { + this->_random = true; + + 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() + { + this->_has_prn = true; + + return *this; + } + + adjective_query& adjective_query::is_variant() + { + this->_is_variant = true; + + return *this; + } + + adjective_query& adjective_query::variant_of(filter _f) + { + _f.clean(); + _variant_of = _f; + + return *this; + } + + adjective_query& adjective_query::has_antonyms() + { + this->_is_antonymic = true; + + return *this; + } + + adjective_query& adjective_query::antonym_of(filter _f) + { + _f.clean(); + _antonym_of = _f; + + return *this; + } + + adjective_query& adjective_query::has_synonyms() + { + this->_is_synonymic = true; + + return *this; + } + + adjective_query& adjective_query::synonym_of(filter _f) + { + _f.clean(); + _synonym_of = _f; + + return *this; + } + + adjective_query& adjective_query::is_generalization() + { + this->_is_generalization = true; + + return *this; + } + + adjective_query& adjective_query::generalization_of(filter _f) + { + _f.clean(); + _generalization_of = _f; + + return *this; + } + + adjective_query& adjective_query::is_specification() + { + this->_is_specification = true; + + return *this; + } + + adjective_query& adjective_query::specification_of(filter _f) + { + _f.clean(); + _specification_of = _f; + + return *this; + } + + adjective_query& adjective_query::is_pertainymic() + { + this->_is_pertainymic = true; + + return *this; + } + + adjective_query& adjective_query::pertainym_of(filter _f) + { + _f.clean(); + _pertainym_of = _f; + + return *this; + } + + adjective_query& adjective_query::is_mannernymic() + { + this->_is_mannernymic = true; + + return *this; + } + + adjective_query& adjective_query::anti_mannernym_of(filter _f) + { + _f.clean(); + _anti_mannernym_of = _f; + + 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"); + } + + 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; + case adjective::positioning::undefined: break; + } + + if (_is_variant) + { + conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)"); + } + + if (!_variant_of.empty()) + { + std::stringstream cond; + if (_variant_of.get_notlogic()) + { + cond << "adjective_id NOT IN"; + } else { + cond << "adjective_id IN"; + } + + cond << "(SELECT adjective_id FROM variation WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "noun_id = @ATTRID"; + } else { + return "noun_id != @ATTRID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_variant_of, _variant_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_antonymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); + } + + if (!_antonym_of.empty()) + { + std::stringstream cond; + if (_antonym_of.get_notlogic()) + { + cond << "adjective_id NOT IN"; + } else { + cond << "adjective_id IN"; + } + + cond << "(SELECT adjective_2_id FROM adjective_antonymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "adjective_1_id = @ANTID"; + } else { + return "adjective_1_id != @ANTID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_antonym_of, _antonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_synonymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); + } + + if (!_synonym_of.empty()) + { + std::stringstream cond; + if (_synonym_of.get_notlogic()) + { + cond << "adjective_id NOT IN"; + } else { + cond << "adjective_id IN"; + } + + cond << "(SELECT adjective_2_id FROM adjective_synonymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "adjective_1_id = @SYNID"; + } else { + return "adjective_1_id != @SYNID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_synonym_of, _synonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_generalization) + { + conditions.push_back("adjective_id IN (SELECT general_id FROM specification)"); + } + + if (!_generalization_of.empty()) + { + std::stringstream cond; + if (_generalization_of.get_notlogic()) + { + cond << "adjective_id NOT IN"; + } else { + cond << "adjective_id IN"; + } + + cond << "(SELECT general_id FROM specification WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "specific_id = @SPECID"; + } else { + return "specific_id != @SPECID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_generalization_of, _generalization_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_specification) + { + conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)"); + } + + if (!_specification_of.empty()) + { + std::stringstream cond; + if (_specification_of.get_notlogic()) + { + cond << "adjective_id NOT IN"; + } else { + cond << "adjective_id IN"; + } + + cond << "(SELECT specific_id FROM specification WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "general_id = @GENID"; + } else { + return "general_id != @GENID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_specification_of, _specification_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_pertainymic) + { + conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)"); + } + + if (!_pertainym_of.empty()) + { + std::stringstream cond; + if (_pertainym_of.get_notlogic()) + { + cond << "adjective_id NOT IN"; + } else { + cond << "adjective_id IN"; + } + + cond << "(SELECT pertainym_id FROM pertainymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "noun_id = @APERID"; + } else { + return "noun_id != @APERID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_pertainym_of, _pertainym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_mannernymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)"); + } + + if (!_anti_mannernym_of.empty()) + { + std::stringstream cond; + if (_anti_mannernym_of.get_notlogic()) + { + cond << "adjective_id NOT IN"; + } else { + cond << "adjective_id IN"; + } + + cond << "(SELECT adjective_id FROM mannernymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "mannernym_id = @MANID"; + } else { + return "mannernym_id != @MANID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_anti_mannernym_of, _anti_mannernym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } +/* + 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.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ATTRID"), attribute._id); + } + + for (auto antonym : _antonym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); + } + + for (auto synonym : _synonym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); + } + + for (auto specific : _generalization_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SPECID"), specific._id); + } + + for (auto general : _specification_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GENID"), general._id); + } + + for (auto n : _pertainym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@APERID"), n._id); + } + + for (auto mannernym : _anti_mannernym_of.inorder_flatten()) + { + 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_query.h b/lib/adjective_query.h new file mode 100644 index 0000000..e7755cb --- /dev/null +++ b/lib/adjective_query.h @@ -0,0 +1,91 @@ +#ifndef ADJECTIVE_QUERY_H_05E590FD +#define ADJECTIVE_QUERY_H_05E590FD + +namespace verbly { + + class adjective_query { + public: + adjective_query(const data& _data); + + adjective_query& limit(int _limit); + adjective_query& random(); + adjective_query& except(const adjective& _word); + adjective_query& rhymes_with(const word& _word); + adjective_query& has_pronunciation(); + + adjective_query& requires_comparative_form(); + adjective_query& requires_superlative_form(); + adjective_query& position(adjective::positioning pos); + + adjective_query& is_variant(); + adjective_query& variant_of(filter _f); + + adjective_query& has_antonyms(); + adjective_query& antonym_of(filter _f); + + adjective_query& has_synonyms(); + adjective_query& synonym_of(filter _f); + + adjective_query& is_generalization(); + adjective_query& generalization_of(filter _f); + + adjective_query& is_specification(); + adjective_query& specification_of(filter _f); + + adjective_query& is_pertainymic(); + adjective_query& pertainym_of(filter _f); + + adjective_query& is_mannernymic(); + adjective_query& anti_mannernym_of(filter _f); + +/* 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; + filter _variant_of; + + bool _is_antonymic = false; + filter _antonym_of; + + bool _is_synonymic = false; + filter _synonym_of; + + bool _is_generalization = false; + filter _generalization_of; + + bool _is_specification = false; + filter _specification_of; + + bool _is_pertainymic = false; + filter _pertainym_of; + + bool _is_mannernymic = false; + filter _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_QUERY_H_05E590FD */ diff --git a/lib/adverb.cpp b/lib/adverb.cpp index 8fcddad..442574e 100644 --- a/lib/adverb.cpp +++ b/lib/adverb.cpp @@ -2,6 +2,11 @@ namespace verbly { + adverb::adverb() + { + + } + adverb::adverb(const data& _data, int _id) : word(_data, _id) { @@ -9,460 +14,58 @@ namespace verbly { std::string adverb::base_form() const { + assert(_valid == true); + return _base_form; } std::string adverb::comparative_form() const { + assert(_valid == true); + return _comparative_form; } std::string adverb::superlative_form() const { + assert(_valid == true); + return _superlative_form; } bool adverb::has_comparative_form() const { + assert(_valid == true); + return !_comparative_form.empty(); } bool adverb::has_superlative_form() const { + assert(_valid == true); + 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); + assert(_valid == true); - return *this; + return _data->adverbs().antonym_of(*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) + adverb_query adverb::synonyms() const { - 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)); - } + assert(_valid == true); - return *this; + return _data->adverbs().synonym_of(*this); } - std::list adverb_query::run() const + adjective_query adverb::anti_mannernyms() 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)"); - } + assert(_valid == true); - 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; + return _data->adjectives().anti_mannernym_of(*this); } }; diff --git a/lib/adverb.h b/lib/adverb.h index 65e3c5c..56d4e28 100644 --- a/lib/adverb.h +++ b/lib/adverb.h @@ -12,6 +12,7 @@ namespace verbly { friend class adverb_query; public: + adverb(); adverb(const data& _data, int _id); std::string base_form() const; @@ -29,67 +30,6 @@ namespace verbly { 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/adverb_query.cpp b/lib/adverb_query.cpp new file mode 100644 index 0000000..639f16f --- /dev/null +++ b/lib/adverb_query.cpp @@ -0,0 +1,514 @@ +#include "verbly.h" + +namespace verbly { + + 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() + { + this->_random = true; + + 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() + { + this->_has_prn = true; + + return *this; + } + + adverb_query& adverb_query::requires_comparative_form() + { + _requires_comparative_form = true; + + return *this; + } + + adverb_query& adverb_query::requires_superlative_form() + { + _requires_superlative_form = true; + + return *this; + } + + adverb_query& adverb_query::has_antonyms() + { + _has_antonyms = true; + + return *this; + } + + adverb_query& adverb_query::antonym_of(filter _f) + { + _f.clean(); + _antonym_of = _f; + + return *this; + } + + adverb_query& adverb_query::has_synonyms() + { + _has_synonyms = true; + + return *this; + } + + adverb_query& adverb_query::synonym_of(filter _f) + { + _f.clean(); + _synonym_of = _f; + + return *this; + } + + adverb_query& adverb_query::is_mannernymic() + { + _is_mannernymic = true; + + return *this; + } + + adverb_query& adverb_query::mannernym_of(filter _f) + { + _f.clean(); + _mannernym_of = _f; + + 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::stringstream cond; + if (_antonym_of.get_notlogic()) + { + cond << "adverb_id NOT IN"; + } else { + cond << "adverb_id IN"; + } + + cond << "(SELECT adverb_2_id FROM adverb_antonymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "adverb_1_id = @ANTID"; + } else { + return "adverb_1_id != @ANTID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_antonym_of, _antonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_has_synonyms) + { + conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)"); + } + + if (!_synonym_of.empty()) + { + std::stringstream cond; + if (_antonym_of.get_notlogic()) + { + cond << "adverb_id NOT IN"; + } else { + cond << "adverb_id IN"; + } + + cond << "(SELECT adverb_2_id FROM adverb_synonymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "adverb_1_id = @SYNID"; + } else { + return "adverb_1_id != @SYNID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_synonym_of, _synonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_mannernymic) + { + conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)"); + } + + if (!_mannernym_of.empty()) + { + std::stringstream cond; + if (_antonym_of.get_notlogic()) + { + cond << "adverb_id NOT IN"; + } else { + cond << "adverb_id IN"; + } + + cond << "(SELECT mannernym_id FROM mannernymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "adjective_id = @AMANID"; + } else { + return "adjective_id != @AMANID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_mannernym_of, _mannernym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + +/* 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.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); + } + + for (auto synonym : _synonym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); + } + + for (auto adj : _mannernym_of.inorder_flatten()) + { + 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_query.h b/lib/adverb_query.h new file mode 100644 index 0000000..20f9ce5 --- /dev/null +++ b/lib/adverb_query.h @@ -0,0 +1,65 @@ +#ifndef ADVERB_QUERY_H_CA13CCDD +#define ADVERB_QUERY_H_CA13CCDD + +namespace verbly { + + class adverb_query { + public: + adverb_query(const data& _data); + + adverb_query& limit(int _limit); + adverb_query& random(); + adverb_query& except(const adverb& _word); + adverb_query& rhymes_with(const word& _word); + adverb_query& has_pronunciation(); + + adverb_query& requires_comparative_form(); + adverb_query& requires_superlative_form(); + + adverb_query& has_antonyms(); + adverb_query& antonym_of(filter _f); + + adverb_query& has_synonyms(); + adverb_query& synonym_of(filter _f); + + adverb_query& is_mannernymic(); + adverb_query& mannernym_of(filter _f); + +/* 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; + filter _antonym_of; + + bool _has_synonyms = false; + filter _synonym_of; + + bool _is_mannernymic = false; + filter _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_QUERY_H_CA13CCDD */ diff --git a/lib/c++14.h b/lib/c++14.h deleted file mode 100644 index b3efbe2..0000000 --- a/lib/c++14.h +++ /dev/null @@ -1,35 +0,0 @@ -#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 index 57a8850..5a9397b 100644 --- a/lib/data.cpp +++ b/lib/data.cpp @@ -46,5 +46,15 @@ namespace verbly { { return noun_query(*this); } - + + frame_query data::frames() const + { + return frame_query(*this); + } + + preposition_query data::prepositions() const + { + return preposition_query(*this); + } + }; diff --git a/lib/data.h b/lib/data.h index 37092d7..6c2d580 100644 --- a/lib/data.h +++ b/lib/data.h @@ -2,7 +2,6 @@ #define DATA_H_C4AEC3DD #include -#include namespace verbly { @@ -12,10 +11,13 @@ namespace verbly { class noun; class verb; class adverb; + class frame; class adjective_query; class adverb_query; class noun_query; class verb_query; + class frame_query; + class preposition_query; class data { private: @@ -25,6 +27,8 @@ namespace verbly { friend class noun_query; friend class verb_query; friend class adverb_query; + friend class frame_query; + friend class preposition_query; public: data(std::string datafile); @@ -41,9 +45,302 @@ namespace verbly { adjective_query adjectives() const; adverb_query adverbs() const; noun_query nouns() const; + frame_query frames() const; + preposition_query prepositions() const; }; + template + class filter { + public: + enum class type { + singleton, + group + }; + + typedef filter value_type; + + type get_type() const + { + return _type; + } + + filter(const filter& other) + { + _type = other._type; + _notlogic = other._notlogic; + + switch (_type) + { + case type::singleton: + { + new(&_singleton.elem) T(other._singleton.elem); + + break; + } + + case type::group: + { + new(&_group.elems) std::list>(other._group.elems); + _group.orlogic = other._group.orlogic; + + break; + } + } + } + + filter& operator=(const filter& other) + { + this->~filter(); + + _type = other._type; + _notlogic = other._notlogic; + + switch (_type) + { + case type::singleton: + { + new(&_singleton.elem) T(other._singleton.elem); + + break; + } + + case type::group: + { + new(&_group.elems) std::list>(other._group.elems); + _group.orlogic = other._group.orlogic; + + break; + } + } + + return *this; + } + + ~filter() + { + switch (_type) + { + case type::singleton: + { + _singleton.elem.~T(); + + break; + } + + case type::group: + { + using list_type = std::list>; + _group.elems.~list_type(); + + break; + } + } + } + + bool get_notlogic() const + { + return _notlogic; + } + + void set_notlogic(bool _nl) + { + _notlogic = _nl; + } + + std::list inorder_flatten() const + { + std::list result; + + if (_type == type::singleton) + { + result.push_back(_singleton.elem); + } else if (_type == type::group) + { + for (auto elem : _group.elems) + { + auto l = elem.inorder_flatten(); + result.insert(std::end(result), std::begin(l), std::end(l)); + } + } + + return result; + } + + std::set uniq_flatten() const + { + std::set result; + + if (_type == type::singleton) + { + result.insert(_singleton.elem); + } else if (_type == type::group) + { + for (auto elem : _group.elems) + { + auto l = elem.uniq_flatten(); + result.insert(std::begin(l), std::end(l)); + } + } + + return result; + } + + void clean() + { + if (_type == type::group) + { + std::list>::iterator> toremove; + for (auto it = _group.elems.begin(); it != _group.elems.end(); it++) + { + it->clean(); + + if (it->get_type() == type::group) + { + if (it->_group.elems.size() == 0) + { + toremove.push_back(it); + } else if (it->_group.elems.size() == 1) + { + bool truelogic = it->_notlogic != it->_group.elems.front()._notlogic; + *it = it->_group.elems.front(); + it->_notlogic = truelogic; + } + } + } + + for (auto rem : toremove) + { + _group.elems.erase(rem); + } + + if (_group.elems.size() == 1) + { + bool truelogic = _notlogic != _group.elems.front()._notlogic; + *this = _group.elems.front(); + _notlogic = truelogic; + } + } + } + + // Singleton + filter(T _elem, bool _notlogic = false) : _type(type::singleton) + { + new(&_singleton.elem) T(_elem); + this->_notlogic = _notlogic; + } + + filter& operator=(T _elem) + { + *this = filter{_elem}; + + return *this; + } + + T get_elem() const + { + assert(_type == type::singleton); + + return _singleton.elem; + } + + void set_elem(T _elem) + { + assert(_type == type::singleton); + + _singleton.elem = _elem; + } + + // Group + typedef typename std::list>::iterator iterator; + + filter() : _type(type::group) + { + new(&_group.elems) std::list>(); + _group.orlogic = false; + } + + filter(std::initializer_list> _init) : _type(type::group) + { + new(&_group.elems) std::list>(_init); + _group.orlogic = false; + } + + iterator begin() + { + assert(_type == type::group); + + return _group.elems.begin(); + } + + iterator end() + { + assert(_type == type::group); + + return _group.elems.end(); + } + + filter& operator<<(filter _elem) + { + assert(_type == type::group); + + _group.elems.push_back(_elem); + + return *this; + } + + void push_back(filter _elem) + { + assert(_type == type::group); + + _group.elems.push_back(_elem); + } + + bool get_orlogic() const + { + assert(_type == type::group); + + return _group.orlogic; + } + + void set_orlogic(bool _ol) + { + assert(_type == type::group); + + _group.orlogic = _ol; + } + + bool empty() const + { + if (_type == type::group) + { + return _group.elems.empty(); + } else { + return false; + } + } + + int size() const + { + assert(_type == type::group); + + return _group.elems.size(); + } + + private: + type _type; + bool _notlogic = false; + union { + struct { + T elem; + } _singleton; + struct { + std::list> elems; + bool orlogic; + } _group; + }; + }; + }; #endif /* end of include guard: DATA_H_C4AEC3DD */ diff --git a/lib/frame.cpp b/lib/frame.cpp new file mode 100644 index 0000000..ccec81b --- /dev/null +++ b/lib/frame.cpp @@ -0,0 +1,320 @@ +#include "verbly.h" + +namespace verbly { + + frame::selrestr::type frame::selrestr::get_type() const + { + return _type; + } + + frame::selrestr::selrestr(const selrestr& other) + { + _type = other._type; + + switch (_type) + { + case frame::selrestr::type::singleton: + { + _singleton.pos = other._singleton.pos; + new(&_singleton.restriction) std::string(other._singleton.restriction); + + break; + } + + case frame::selrestr::type::group: + { + new(&_group.children) std::list(other._group.children); + _group.orlogic = other._group.orlogic; + + break; + } + + case frame::selrestr::type::empty: + { + // Nothing! + + break; + } + } + } + + frame::selrestr::~selrestr() + { + switch (_type) + { + case frame::selrestr::type::singleton: + { + using string_type = std::string; + _singleton.restriction.~string_type(); + + break; + } + + case frame::selrestr::type::group: + { + using list_type = std::list; + _group.children.~list_type(); + + break; + } + + case frame::selrestr::type::empty: + { + // Nothing! + + break; + } + } + } + + frame::selrestr& frame::selrestr::operator=(const selrestr& other) + { + this->~selrestr(); + + _type = other._type; + + switch (_type) + { + case frame::selrestr::type::singleton: + { + _singleton.pos = other._singleton.pos; + new(&_singleton.restriction) std::string(other._singleton.restriction); + + break; + } + + case frame::selrestr::type::group: + { + new(&_group.children) std::list(other._group.children); + _group.orlogic = other._group.orlogic; + + break; + } + + case frame::selrestr::type::empty: + { + // Nothing! + + break; + } + } + + return *this; + } + + frame::selrestr::selrestr() : _type(frame::selrestr::type::empty) + { + + } + + frame::selrestr::selrestr(std::string restriction, bool pos) : _type(frame::selrestr::type::singleton) + { + new(&_singleton.restriction) std::string(restriction); + _singleton.pos = pos; + } + + std::string frame::selrestr::get_restriction() const + { + assert(_type == frame::selrestr::type::singleton); + + return _singleton.restriction; + } + + bool frame::selrestr::get_pos() const + { + assert(_type == frame::selrestr::type::singleton); + + return _singleton.pos; + } + + frame::selrestr::selrestr(std::list children, bool orlogic) : _type(frame::selrestr::type::group) + { + new(&_group.children) std::list(children); + _group.orlogic = orlogic; + } + + std::list frame::selrestr::get_children() const + { + assert(_type == frame::selrestr::type::group); + + return _group.children; + } + + std::list::const_iterator frame::selrestr::begin() const + { + assert(_type == frame::selrestr::type::group); + + return _group.children.begin(); + } + + std::list::const_iterator frame::selrestr::end() const + { + assert(_type == frame::selrestr::type::group); + + return _group.children.end(); + } + + bool frame::selrestr::get_orlogic() const + { + assert(_type == frame::selrestr::type::group); + + return _group.orlogic; + } + + frame::part::type frame::part::get_type() const + { + return _type; + } + + frame::part::part() + { + + } + + frame::part::part(const part& other) + { + _type = other._type; + + switch (_type) + { + case frame::part::type::noun_phrase: + { + new(&_noun_phrase.role) std::string(other._noun_phrase.role); + new(&_noun_phrase.selrestrs) selrestr(other._noun_phrase.selrestrs); + new(&_noun_phrase.synrestrs) std::set(other._noun_phrase.synrestrs); + + break; + } + + case frame::part::type::literal_preposition: + { + new(&_literal_preposition.choices) std::vector(other._literal_preposition.choices); + + break; + } + + case frame::part::type::selection_preposition: + { + new(&_selection_preposition.preprestrs) std::vector(other._selection_preposition.preprestrs); + + break; + } + + case frame::part::type::literal: + { + new(&_literal.lexval) std::string(other._literal.lexval); + + break; + } + + default: + { + // Nothing! + + break; + } + } + } + + frame::part::~part() + { + switch (_type) + { + case frame::part::type::noun_phrase: + { + using string_type = std::string; + using set_type = std::set; + + _noun_phrase.role.~string_type(); + _noun_phrase.selrestrs.~selrestr(); + _noun_phrase.synrestrs.~set_type(); + + break; + } + + case frame::part::type::literal_preposition: + { + using vector_type = std::vector; + _literal_preposition.choices.~vector_type(); + + break; + } + + case frame::part::type::selection_preposition: + { + using vector_type = std::vector; + _selection_preposition.preprestrs.~vector_type(); + + break; + } + + case frame::part::type::literal: + { + using string_type = std::string; + _literal.lexval.~string_type(); + + break; + } + + default: + { + // Nothing! + + break; + } + } + } + + std::string frame::part::get_role() const + { + assert(_type == frame::part::type::noun_phrase); + + return _noun_phrase.role; + } + + frame::selrestr frame::part::get_selrestrs() const + { + assert(_type == frame::part::type::noun_phrase); + + return _noun_phrase.selrestrs; + } + + std::set frame::part::get_synrestrs() const + { + assert(_type == frame::part::type::noun_phrase); + + return _noun_phrase.synrestrs; + } + + std::vector frame::part::get_choices() const + { + assert(_type == frame::part::type::literal_preposition); + + return _literal_preposition.choices; + } + + std::vector frame::part::get_preprestrs() const + { + assert(_type == frame::part::type::selection_preposition); + + return _selection_preposition.preprestrs; + } + + std::string frame::part::get_literal() const + { + assert(_type == frame::part::type::literal); + + return _literal.lexval; + } + + std::vector frame::parts() const + { + return _parts; + } + + std::map frame::roles() const + { + return _roles; + } + +}; diff --git a/lib/frame.h b/lib/frame.h new file mode 100644 index 0000000..fa57e1b --- /dev/null +++ b/lib/frame.h @@ -0,0 +1,118 @@ +#ifndef FRAME_H_9A5D90FE +#define FRAME_H_9A5D90FE + +namespace verbly { + + class frame_query; + + class frame { + public: + class selrestr { + public: + enum class type { + empty, + singleton, + group + }; + + type get_type() const; + selrestr(const selrestr& other); + ~selrestr(); + selrestr& operator=(const selrestr& other); + + // Empty + selrestr(); + + // Singleton + selrestr(std::string restriction, bool pos); + std::string get_restriction() const; + bool get_pos() const; + + // Group + selrestr(std::list children, bool orlogic); + std::list get_children() const; + std::list::const_iterator begin() const; + std::list::const_iterator end() const; + bool get_orlogic() const; + + private: + union { + struct { + bool pos; + std::string restriction; + } _singleton; + struct { + std::list children; + bool orlogic; + } _group; + }; + type _type; + }; + + class part { + public: + enum class type { + noun_phrase, + verb, + literal_preposition, + selection_preposition, + adjective, + adverb, + literal + }; + + type get_type() const; + part(const part& other); + ~part(); + + // Noun phrase + std::string get_role() const; + selrestr get_selrestrs() const; + std::set get_synrestrs() const; + + // Literal preposition + std::vector get_choices() const; + + // Selection preposition + std::vector get_preprestrs() const; + + // Literal + std::string get_literal() const; + + private: + friend class frame_query; + + part(); + + union { + struct { + std::string role; + selrestr selrestrs; + std::set synrestrs; + } _noun_phrase; + struct { + std::vector choices; + } _literal_preposition; + struct { + std::vector preprestrs; + } _selection_preposition; + struct { + std::string lexval; + } _literal; + }; + type _type; + }; + + std::vector parts() const; + std::map roles() const; + + private: + friend class frame_query; + + std::vector _parts; + std::map _roles; + }; + +}; + +#endif /* end of include guard: FRAME_H_9A5D90FE */ diff --git a/lib/frame_query.cpp b/lib/frame_query.cpp new file mode 100644 index 0000000..6583da4 --- /dev/null +++ b/lib/frame_query.cpp @@ -0,0 +1,142 @@ +#include "verbly.h" +#include + +using json = nlohmann::json; + +namespace verbly { + + frame_query::frame_query(const data& _data) : _data(_data) + { + + } + + frame_query& frame_query::for_verb(const verb& _v) + { + _for_verb.push_back(_v); + + return *this; + } + + frame::selrestr parse_selrestr(const json data) + { + if (data.find("children") != data.end()) + { + std::list children; + std::transform(std::begin(data["children"]), std::end(data["children"]), std::back_inserter(children), &parse_selrestr); + + return frame::selrestr{children, data["logic"] == "or"}; + } else if (data.find("type") != data.end()) + { + return frame::selrestr{data["type"].get(), data["pos"].get()}; + } else { + return frame::selrestr{}; + } + } + + std::list frame_query::run() const + { + std::stringstream construct; + construct << "SELECT frames.data, groups.data FROM frames INNER JOIN groups ON frames.group_id = groups.group_id"; + + if (!_for_verb.empty()) + { + std::list clauses(_for_verb.size(), "verb_id = @VERID"); + construct << " WHERE frames.group_id IN (SELECT group_id FROM verb_groups WHERE "; + construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); + construct << ")"; + } + + 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)); + } + + for (auto verb : _for_verb) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VERID"), verb._id); + } + + std::list output; + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + frame f; + + std::string fdatat(reinterpret_cast(sqlite3_column_blob(ppstmt, 0))); + const json fdata = json::parse(fdatat); + for (const auto& part : fdata) + { + frame::part p; + + if (part["type"] == "np") + { + p._type = frame::part::type::noun_phrase; + new(&p._noun_phrase.role) std::string(part["role"].get()); + new(&p._noun_phrase.selrestrs) frame::selrestr(parse_selrestr(part["selrestrs"])); + new(&p._noun_phrase.synrestrs) std::set(); + for (auto synrestr : part["synrestrs"]) + { + p._noun_phrase.synrestrs.insert(synrestr.get()); + } + } else if (part["type"] == "pp") + { + if (!part["values"].empty()) + { + p._type = frame::part::type::literal_preposition; + new(&p._literal_preposition.choices) std::vector(); + for (auto choice : part["values"]) + { + p._literal_preposition.choices.push_back(choice.get()); + } + } else if (!part["preprestrs"].empty()) + { + p._type = frame::part::type::selection_preposition; + new(&p._selection_preposition.preprestrs) std::vector(); + for (auto preprestr : part["preprestrs"]) + { + p._selection_preposition.preprestrs.push_back(preprestr.get()); + } + } + } else if (part["type"] == "v") + { + p._type = frame::part::type::verb; + } else if (part["type"] == "adj") + { + p._type = frame::part::type::adjective; + } else if (part["type"] == "adv") + { + p._type = frame::part::type::adverb; + } else if (part["type"] == "lex") + { + p._type = frame::part::type::literal; + new(&p._literal.lexval) std::string(part["value"].get()); + } + + f._parts.push_back(p); + } + + std::string rdatat(reinterpret_cast(sqlite3_column_blob(ppstmt, 1))); + const json rdata = json::parse(rdatat); + for (const auto& role : rdata) + { + std::string rt = role["type"]; + frame::selrestr rs; + + if (role.find("selrestrs") != role.end()) + { + rs = parse_selrestr(role["selrestrs"]); + } + + f._roles[rt] = rs; + } + + output.push_back(f); + } + + sqlite3_finalize(ppstmt); + + return output; + } + +}; diff --git a/lib/frame_query.h b/lib/frame_query.h new file mode 100644 index 0000000..dd11d16 --- /dev/null +++ b/lib/frame_query.h @@ -0,0 +1,21 @@ +#ifndef FRAME_QUERY_H_334B9D47 +#define FRAME_QUERY_H_334B9D47 + +namespace verbly { + + class frame_query { + public: + frame_query(const data& _data); + + frame_query& for_verb(const verb& _v); + + std::list run() const; + + private: + const data& _data; + std::list _for_verb; + }; + +}; + +#endif /* end of include guard: FRAME_QUERY_H_334B9D47 */ diff --git a/lib/noun.cpp b/lib/noun.cpp index 81e6613..f575117 100644 --- a/lib/noun.cpp +++ b/lib/noun.cpp @@ -1,7 +1,14 @@ #include "verbly.h" +#include +#include namespace verbly { + noun::noun() + { + + } + noun::noun(const data& _data, int _id) : word(_data, _id) { @@ -9,1036 +16,147 @@ namespace verbly { std::string noun::base_form() const { + assert(_valid == true); + return _singular; } std::string noun::singular_form() const { + assert(_valid == true); + return _singular; } std::string noun::plural_form() const { + assert(_valid == true); + return _plural; } bool noun::has_plural_form() const { + assert(_valid == true); + 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); + assert(_valid == true); - return *this; + return _data->nouns().hypernym_of(*this); } - noun_query& noun_query::not_part_meronym_of(const noun& _noun) + noun_query noun::full_hypernyms() const { - _not_part_meronym_of.push_back(_noun); + assert(_valid == true); - return *this; + return _data->nouns().full_hypernym_of(*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::is_instance(bool _arg) - { - _is_instance = _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) + noun_query noun::hyponyms() const { - _class_of.push_back(_noun); + assert(_valid == true); - return *this; + return _data->nouns().hyponym_of(*this); } - noun_query& noun_query::not_class_of(const noun& _noun) + noun_query noun::full_hyponyms() const { - _not_class_of.push_back(_noun); + assert(_valid == true); - return *this; + return _data->nouns().full_hyponym_of(*this); } - noun_query& noun_query::has_synonyms(bool _arg) + noun_query noun::part_meronyms() const { - _has_synonyms = _arg; + assert(_valid == true); - return *this; + return _data->nouns().part_meronym_of(*this); } - noun_query& noun_query::synonym_of(const noun& _noun) + noun_query noun::part_holonyms() const { - _synonym_of.push_back(_noun); + assert(_valid == true); - return *this; + return _data->nouns().part_holonym_of(*this); } - noun_query& noun_query::not_synonym_of(const noun& _noun) + noun_query noun::substance_meronyms() const { - _not_synonym_of.push_back(_noun); + assert(_valid == true); - return *this; + return _data->nouns().substance_meronym_of(*this); } - noun_query& noun_query::has_antonyms(bool _arg) + noun_query noun::substance_holonyms() const { - _has_antonyms = _arg; + assert(_valid == true); - return *this; + return _data->nouns().substance_holonym_of(*this); } - noun_query& noun_query::antonym_of(const noun& _noun) + noun_query noun::member_meronyms() const { - _antonym_of.push_back(_noun); + assert(_valid == true); - return *this; + return _data->nouns().member_meronym_of(*this); } - noun_query& noun_query::not_antonym_of(const noun& _noun) + noun_query noun::member_holonyms() const { - _not_antonym_of.push_back(_noun); + assert(_valid == true); - return *this; + return _data->nouns().member_holonym_of(*this); } - noun_query& noun_query::has_pertainym(bool _arg) + noun_query noun::classes() const { - _has_pertainym = _arg; + assert(_valid == true); - return *this; + return _data->nouns().class_of(*this); } - noun_query& noun_query::anti_pertainym_of(const adjective& _adj) + noun_query noun::instances() const { - _anti_pertainym_of.push_back(_adj); + assert(_valid == true); - return *this; + return _data->nouns().instance_of(*this); } - noun_query& noun_query::is_attribute(bool _arg) + noun_query noun::synonyms() const { - _is_attribute = _arg; + assert(_valid == true); - return *this; + return _data->nouns().synonym_of(*this); } - noun_query& noun_query::attribute_of(const adjective& _adj) + noun_query noun::antonyms() const { - _attribute_of.push_back(_adj); + assert(_valid == true); - return *this; + return _data->nouns().antonym_of(*this); } - noun_query& noun_query::derived_from(const word& _w) + adjective_query noun::pertainyms() const { - 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)); - } + assert(_valid == true); - return *this; + return _data->adjectives().pertainym_of(*this); } - noun_query& noun_query::not_derived_from(const word& _w) + adjective_query noun::variations() const { - 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)); - } + assert(_valid == true); - return *this; + return _data->adjectives().variant_of(*this); } - std::list noun_query::run() const + bool noun::operator<(const noun& other) 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("proper = 1"); - } - - if (_is_not_proper) - { - conditions.push_back("proper = 0"); - } - - if (_is_instance) - { - conditions.push_back("noun_id 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; + return _id < other._id; } }; diff --git a/lib/noun.h b/lib/noun.h index fbc2f9e..77601d0 100644 --- a/lib/noun.h +++ b/lib/noun.h @@ -11,6 +11,7 @@ namespace verbly { friend class noun_query; public: + noun(); noun(const data& _data, int _id); std::string base_form() const; @@ -20,7 +21,9 @@ namespace verbly { bool has_plural_form() const; noun_query hypernyms() const; + noun_query full_hypernyms() const; noun_query hyponyms() const; + noun_query full_hyponyms() const; noun_query part_meronyms() const; noun_query part_holonyms() const; noun_query substance_meronyms() const; @@ -33,153 +36,8 @@ namespace verbly { 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& is_instance(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; - - bool _is_instance = 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; + bool operator<(const noun& other) const; }; }; diff --git a/lib/noun_query.cpp b/lib/noun_query.cpp new file mode 100644 index 0000000..cb11577 --- /dev/null +++ b/lib/noun_query.cpp @@ -0,0 +1,1453 @@ +#include "verbly.h" + +namespace verbly { + + 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() + { + this->_random = true; + + 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() + { + this->_has_prn = true; + + return *this; + } + + noun_query& noun_query::with_singular_form(std::string _arg) + { + _with_singular_form.push_back(_arg); + + return *this; + } + + noun_query& noun_query::is_hypernym() + { + _is_hypernym = true; + + return *this; + } + + noun_query& noun_query::hypernym_of(filter _f) + { + _f.clean(); + _hypernym_of = _f; + + return *this; + } + + noun_query& noun_query::full_hypernym_of(filter _f) + { + _f.clean(); + _full_hypernym_of = _f; + + return *this; + } + + noun_query& noun_query::is_hyponym() + { + _is_hyponym = true; + + return *this; + } + + noun_query& noun_query::hyponym_of(filter _f) + { + _f.clean(); + _hyponym_of = _f; + + return *this; + } + + noun_query& noun_query::full_hyponym_of(filter _f) + { + _f.clean(); + _full_hyponym_of = _f; + + return *this; + } + + noun_query& noun_query::is_part_meronym() + { + _is_part_meronym = true; + + return *this; + } + + noun_query& noun_query::part_meronym_of(filter _f) + { + _f.clean(); + _part_meronym_of = _f; + + return *this; + } + + noun_query& noun_query::is_part_holonym() + { + _is_part_holonym = true; + + return *this; + } + + noun_query& noun_query::part_holonym_of(filter _f) + { + _f.clean(); + _part_holonym_of = _f; + + return *this; + } + + noun_query& noun_query::is_substance_meronym() + { + _is_substance_meronym = true; + + return *this; + } + + noun_query& noun_query::substance_meronym_of(filter _f) + { + _f.clean(); + _substance_meronym_of = _f; + + return *this; + } + + noun_query& noun_query::is_substance_holonym() + { + _is_substance_holonym = true; + + return *this; + } + + noun_query& noun_query::substance_holonym_of(filter _f) + { + _f.clean(); + _substance_holonym_of = _f; + + return *this; + } + + noun_query& noun_query::is_member_meronym() + { + _is_member_meronym = true; + + return *this; + } + + noun_query& noun_query::member_meronym_of(filter _f) + { + _f.clean(); + _member_meronym_of = _f; + + return *this; + } + + noun_query& noun_query::is_member_holonym() + { + _is_member_holonym = true; + + return *this; + } + + noun_query& noun_query::member_holonym_of(filter _f) + { + _f.clean(); + _member_holonym_of = _f; + + return *this; + } + + noun_query& noun_query::is_proper() + { + _is_proper = true; + + return *this; + } + + noun_query& noun_query::is_not_proper() + { + _is_not_proper = true; + + return *this; + } + + noun_query& noun_query::is_instance() + { + _is_instance = true; + + return *this; + } + + noun_query& noun_query::instance_of(filter _f) + { + _f.clean(); + _instance_of = _f; + + return *this; + } + + noun_query& noun_query::is_class() + { + _is_class = true; + + return *this; + } + + noun_query& noun_query::class_of(filter _f) + { + _f.clean(); + _class_of = _f; + + return *this; + } + + noun_query& noun_query::has_synonyms() + { + _has_synonyms = true; + + return *this; + } + + noun_query& noun_query::synonym_of(filter _f) + { + _f.clean(); + _synonym_of = _f; + + return *this; + } + + noun_query& noun_query::has_antonyms() + { + _has_antonyms = true; + + return *this; + } + + noun_query& noun_query::antonym_of(filter _f) + { + _f.clean(); + _antonym_of = _f; + + return *this; + } + + noun_query& noun_query::has_pertainym() + { + _has_pertainym = true; + + return *this; + } + + noun_query& noun_query::anti_pertainym_of(filter _f) + { + _f.clean(); + _anti_pertainym_of = _f; + + return *this; + } + + noun_query& noun_query::is_attribute() + { + _is_attribute = true; + + return *this; + } + + noun_query& noun_query::attribute_of(filter _f) + { + _f.clean(); + _attribute_of = _f; + + 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; + + if (!_full_hypernym_of.empty() || !_full_hyponym_of.empty()) + { + construct << "WITH RECURSIVE "; + + std::list ctes; + + for (auto hyponym : _full_hypernym_of.uniq_flatten()) + { + ctes.push_back("hypernym_tree_" + std::to_string(hyponym._id) + " AS (SELECT hypernym_id FROM hypernymy WHERE hyponym_id = " + std::to_string(hyponym._id) + " UNION SELECT h.hypernym_id FROM hypernym_tree_" + std::to_string(hyponym._id) + " AS t INNER JOIN hypernymy AS h ON t.hypernym_id = h.hyponym_id)"); + } + + for (auto hypernym : _full_hyponym_of.uniq_flatten()) + { + ctes.push_back("hyponym_tree_" + std::to_string(hypernym._id) + " AS (SELECT hyponym_id FROM hypernymy WHERE hypernym_id = " + std::to_string(hypernym._id) + " UNION SELECT h.hyponym_id FROM hyponym_tree_" + std::to_string(hypernym._id) + " AS t INNER JOIN hypernymy AS h ON t.hyponym_id = h.hypernym_id)"); + } + + construct << verbly::implode(std::begin(ctes), std::end(ctes), ", "); + 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 (!_with_singular_form.empty()) + { + std::list clauses(_with_singular_form.size(), "singular = @SFORM"); + std::string cond = "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_hypernym) + { + conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)"); + } + + if (!_hypernym_of.empty()) + { + std::stringstream cond; + if (_hypernym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT hypernym_id FROM hypernymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "hyponym_id = @HYPO"; + } else { + return "hyponym_id != @HYPO"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_hypernym_of, _hypernym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (!_full_hypernym_of.empty()) + { + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "noun_id IN (SELECT hypernym_id FROM hypernym_tree_" + std::to_string(f.get_elem()._id) + ")"; + } else { + return "noun_id NOT IN (SELECT hypernym_id FROM hypernym_tree_" + std::to_string(f.get_elem()._id) + ")"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + conditions.push_back(recur(_full_hypernym_of, false)); + } + + if (!_full_hyponym_of.empty()) + { + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "noun_id IN (SELECT hyponym_id FROM hyponym_tree_" + std::to_string(f.get_elem()._id) + ")"; + } else { + return "noun_id NOT IN (SELECT hyponym_id FROM hyponym_tree_" + std::to_string(f.get_elem()._id) + ")"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + conditions.push_back(recur(_full_hyponym_of, false)); + } + + if (_is_hyponym) + { + conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)"); + } + + if (!_hyponym_of.empty()) + { + std::stringstream cond; + if (_hyponym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT hyponym_id FROM hypernymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "hypernym_id = @HYPER"; + } else { + return "hypernym_id != @HYPER"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_hyponym_of, _hyponym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_part_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)"); + } + + if (!_part_meronym_of.empty()) + { + std::stringstream cond; + if (_part_meronym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT meronym_id FROM part_meronymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "holonym_id = @PHOLO"; + } else { + return "holonym_id != @PHOLO"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_part_meronym_of, _part_meronym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_part_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)"); + } + + if (!_part_holonym_of.empty()) + { + std::stringstream cond; + if (_part_holonym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT holonym_id FROM part_meronymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "meronym_id = @PMERO"; + } else { + return "meronym_id != @PMERO"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_part_holonym_of, _part_holonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_substance_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)"); + } + + if (!_substance_meronym_of.empty()) + { + std::stringstream cond; + if (_substance_meronym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT meronym_id FROM substance_meronymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "holonym_id = @SHOLO"; + } else { + return "holonym_id != @SHOLO"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_substance_meronym_of, _substance_meronym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_substance_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)"); + } + + if (!_substance_holonym_of.empty()) + { + std::stringstream cond; + if (_substance_holonym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT holonym_id FROM substance_meronymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "meronym_id = @SMERO"; + } else { + return "meronym_id != @SMERO"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_substance_holonym_of, _substance_holonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_member_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)"); + } + + if (!_member_meronym_of.empty()) + { + std::stringstream cond; + if (_member_meronym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT meronym_id FROM member_meronymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "holonym_id = @MHOLO"; + } else { + return "holonym_id != @MHOLO"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_member_meronym_of, _member_meronym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_member_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)"); + } + + if (!_member_holonym_of.empty()) + { + std::stringstream cond; + if (_member_holonym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT holonym_id FROM member_meronymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "meronym_id = @MMERO"; + } else { + return "meronym_id != @MMERO"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_member_holonym_of, _member_holonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_proper) + { + conditions.push_back("proper = 1"); + } + + if (_is_not_proper) + { + conditions.push_back("proper = 0"); + } + + if (_is_instance) + { + conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)"); + } + + if (!_instance_of.empty()) + { + std::stringstream cond; + if (_instance_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT instance_id FROM instantiation WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "class_id = @CLSID"; + } else { + return "class_id != @CLSID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_instance_of, _instance_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_class) + { + conditions.push_back("noun_id IN (SELECT class_id FROM instantiation)"); + } + + if (!_class_of.empty()) + { + std::stringstream cond; + if (_class_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT class_id FROM instantiation WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "instance_id = @INSID"; + } else { + return "instance_id != @INSID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_class_of, _class_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_has_synonyms) + { + conditions.push_back("noun_id IN (SELECT noun_2_id FROM noun_synonymy)"); + } + + if (!_synonym_of.empty()) + { + std::stringstream cond; + if (_synonym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT noun_2_id FROM noun_synonymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "noun_1_id = @SYNID"; + } else { + return "noun_1_id != @SYNID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_synonym_of, _synonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_has_antonyms) + { + conditions.push_back("noun_id IN (SELECT noun_2_id FROM noun_antonymy)"); + } + + if (!_antonym_of.empty()) + { + std::stringstream cond; + if (_antonym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT noun_2_id FROM noun_antonymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "noun_1_id = @ANTID"; + } else { + return "noun_1_id != @ANTID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_antonym_of, _antonym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_has_pertainym) + { + conditions.push_back("noun_id IN (SELECT noun_id FROM pertainymy)"); + } + + if (!_anti_pertainym_of.empty()) + { + std::stringstream cond; + if (_anti_pertainym_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT noun_id FROM pertainymy WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "pertainym_id = @PERID"; + } else { + return "pertainym_id != @PERID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_anti_pertainym_of, _anti_pertainym_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + + if (_is_attribute) + { + conditions.push_back("noun_id IN (SELECT noun_id FROM variation)"); + } + + if (!_attribute_of.empty()) + { + std::stringstream cond; + if (_attribute_of.get_notlogic()) + { + cond << "noun_id NOT IN"; + } else { + cond << "noun_id IN"; + } + + cond << "(SELECT noun_id FROM variation WHERE "; + + std::function, bool)> recur = [&] (filter f, bool notlogic) -> std::string { + switch (f.get_type()) + { + case filter::type::singleton: + { + if (notlogic == f.get_notlogic()) + { + return "adjective_id = @VALID"; + } else { + return "adjective_id != @VALID"; + } + } + + case filter::type::group: + { + bool truelogic = notlogic != f.get_notlogic(); + + std::list clauses; + std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter f2) { + return recur(f2, truelogic); + }); + + if (truelogic == f.get_orlogic()) + { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; + } else { + return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + } + } + } + }; + + cond << recur(_attribute_of, _attribute_of.get_notlogic()); + cond << ")"; + conditions.push_back(cond.str()); + } + /* + 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 sform : _with_singular_form) + { + sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SFORM"), sform.c_str(), sform.size(), SQLITE_STATIC); + } + + for (auto hyponym : _hypernym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPO"), hyponym._id); + } + + for (auto hypernym : _hyponym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPER"), hypernym._id); + } + + for (auto holonym : _part_meronym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PHOLO"), holonym._id); + } + + for (auto meronym : _part_holonym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PMERO"), meronym._id); + } + + for (auto holonym : _substance_meronym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SHOLO"), holonym._id); + } + + for (auto meronym : _substance_holonym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SMERO"), meronym._id); + } + + for (auto holonym : _member_meronym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MHOLO"), holonym._id); + } + + for (auto meronym : _member_holonym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MMERO"), meronym._id); + } + + for (auto cls : _instance_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@CLSID"), cls._id); + } + + for (auto inst : _class_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@INSID"), inst._id); + } + + for (auto synonym : _synonym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); + } + + for (auto antonym : _antonym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); + } + + for (auto pertainym : _anti_pertainym_of.inorder_flatten()) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PERID"), pertainym._id); + } + + for (auto value : _attribute_of.inorder_flatten()) + { + 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_query.h b/lib/noun_query.h new file mode 100644 index 0000000..0c41a68 --- /dev/null +++ b/lib/noun_query.h @@ -0,0 +1,139 @@ +#ifndef NOUN_QUERY_H_5DE51DD7 +#define NOUN_QUERY_H_5DE51DD7 + +namespace verbly { + + class noun_query { + public: + noun_query(const data& _data); + + noun_query& limit(int _limit); + noun_query& random(); + noun_query& except(const noun& _word); + noun_query& rhymes_with(const word& _word); + noun_query& has_pronunciation(); + + noun_query& with_singular_form(std::string _arg); + + noun_query& is_hypernym(); + noun_query& hypernym_of(filter _f); + noun_query& full_hypernym_of(filter _f); + + noun_query& is_hyponym(); + noun_query& hyponym_of(filter _f); + noun_query& full_hyponym_of(filter _f); + + noun_query& is_part_meronym(); + noun_query& part_meronym_of(filter _f); + + noun_query& is_part_holonym(); + noun_query& part_holonym_of(filter _f); + + noun_query& is_substance_meronym(); + noun_query& substance_meronym_of(filter _f); + + noun_query& is_substance_holonym(); + noun_query& substance_holonym_of(filter _f); + + noun_query& is_member_meronym(); + noun_query& member_meronym_of(filter _f); + + noun_query& is_member_holonym(); + noun_query& member_holonym_of(filter _f); + + noun_query& is_proper(); + noun_query& is_not_proper(); + + noun_query& is_instance(); + noun_query& instance_of(filter _f); + + noun_query& is_class(); + noun_query& class_of(filter _f); + + noun_query& has_synonyms(); + noun_query& synonym_of(filter _f); + + noun_query& has_antonyms(); + noun_query& antonym_of(filter _f); + + noun_query& has_pertainym(); + noun_query& anti_pertainym_of(filter _f); + + noun_query& is_attribute(); + noun_query& attribute_of(filter _f); + +/* 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; + + std::list _with_singular_form; + + bool _is_hypernym = false; + filter _hypernym_of; + filter _full_hypernym_of; + + bool _is_hyponym = false; + filter _hyponym_of; + filter _full_hyponym_of; + + bool _is_part_meronym = false; + filter _part_meronym_of; + + bool _is_substance_meronym = false; + filter _substance_meronym_of; + + bool _is_member_meronym = false; + filter _member_meronym_of; + + bool _is_part_holonym = false; + filter _part_holonym_of; + + bool _is_substance_holonym = false; + filter _substance_holonym_of; + + bool _is_member_holonym = false; + filter _member_holonym_of; + + bool _is_proper = false; + bool _is_not_proper = false; + + bool _is_instance = false; + filter _instance_of; + + bool _is_class = false; + filter _class_of; + + bool _has_synonyms = false; + filter _synonym_of; + + bool _has_antonyms = false; + filter _antonym_of; + + bool _has_pertainym = false; + filter _anti_pertainym_of; + + bool _is_attribute = false; + filter _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_QUERY_H_5DE51DD7 */ diff --git a/lib/preposition.cpp b/lib/preposition.cpp new file mode 100644 index 0000000..c619bbf --- /dev/null +++ b/lib/preposition.cpp @@ -0,0 +1,83 @@ +#include "verbly.h" + +namespace verbly { + + std::string preposition::get_form() const + { + return form; + } + + preposition_query::preposition_query(const data& _data) : _data(_data) + { + + } + + preposition_query& preposition_query::limit(int _limit) + { + this->_limit = _limit; + + return *this; + } + + preposition_query& preposition_query::random() + { + _random = true; + + return *this; + } + + preposition_query& preposition_query::in_group(std::string _arg) + { + _in_group.push_back(_arg); + + return *this; + } + + std::list preposition_query::run() const + { + std::stringstream construct; + construct << "SELECT form FROM prepositions"; + + if (!_in_group.empty()) + { + std::list clauses(_in_group.size(), "groupname = @GNAME"); + construct << " WHERE preposition_id IN (SELECT preposition_id FROM preposition_groups WHERE "; + construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); + construct << ")"; + } + + 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)); + } + + for (auto& group : _in_group) + { + sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GNAME"), group.c_str(), group.length(), SQLITE_STATIC); + } + + std::list output; + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + preposition pp; + pp.form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 0))); + + output.push_back(pp); + } + + return output; + } + +}; diff --git a/lib/preposition.h b/lib/preposition.h new file mode 100644 index 0000000..89f24fa --- /dev/null +++ b/lib/preposition.h @@ -0,0 +1,38 @@ +#ifndef PREPOSITION_H_FF908021 +#define PREPOSITION_H_FF908021 + +namespace verbly { + + class preposition_query; + + class preposition { + public: + std::string get_form() const; + + private: + friend class preposition_query; + + std::string form; + }; + + class preposition_query { + public: + preposition_query(const data& _data); + + preposition_query& limit(int _limit); + preposition_query& random(); + preposition_query& in_group(std::string _arg); + + std::list run() const; + + const static int unlimited = -1; + private: + const data& _data; + int _limit = unlimited; + bool _random = false; + std::list _in_group; + }; + +}; + +#endif /* end of include guard: PREPOSITION_H_FF908021 */ diff --git a/lib/token.cpp b/lib/token.cpp index facab8a..1e25acb 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2,52 +2,627 @@ namespace verbly { - token::token(token::type _type) : _type(_type) + token::type token::get_type() const { - + return _type; } - token::type token::token_type() const + int token::get_extra() const { - return _type; + return _extra; } - verb_token::verb_token(const verb& _verb) : token(token::type::verb), _verb(&_verb) + void token::set_extra(int _arg) { - + _extra = _arg; } - const verb& verb_token::get_verb() const + token::token(const token& other) { - return *_verb; + _type = other._type; + + switch (_type) + { + case token::type::verb: + { + new(&_verb._verb) verb(other._verb._verb); + _verb._infl = other._verb._infl; + + break; + } + + case token::type::noun: + { + new(&_noun._noun) noun(other._noun._noun); + _noun._infl = other._noun._infl; + + break; + } + + case token::type::adjective: + { + new(&_adjective._adjective) adjective(other._adjective._adjective); + _adjective._infl = other._adjective._infl; + + break; + } + + case token::type::adverb: + { + new(&_adverb._adverb) adverb(other._adverb._adverb); + _adverb._infl = other._adverb._infl; + + break; + } + + case token::type::preposition: + { + new(&_preposition._preposition) preposition(other._preposition._preposition); + + break; + } + + case token::type::fillin: + { + _fillin._type = other._fillin._type; + + break; + } + + case token::type::string: + { + new(&_string._str) std::string(other._string._str); + + break; + } + + case token::type::utterance: + { + new(&_utterance._utterance) std::list(other._utterance._utterance); + + break; + } + } } - verb_token& verb_token::inflect(verb_token::inflection infl) + token& token::operator=(const token& other) { - _inflection = infl; + this->~token(); + + _type = other._type; + + switch (_type) + { + case token::type::verb: + { + new(&_verb._verb) verb(other._verb._verb); + _verb._infl = other._verb._infl; + + break; + } + + case token::type::noun: + { + new(&_noun._noun) noun(other._noun._noun); + _noun._infl = other._noun._infl; + + break; + } + + case token::type::adjective: + { + new(&_adjective._adjective) adjective(other._adjective._adjective); + _adjective._infl = other._adjective._infl; + + break; + } + + case token::type::adverb: + { + new(&_adverb._adverb) adverb(other._adverb._adverb); + _adverb._infl = other._adverb._infl; + + break; + } + + case token::type::preposition: + { + new(&_preposition._preposition) preposition(other._preposition._preposition); + + break; + } + + case token::type::fillin: + { + _fillin._type = other._fillin._type; + + break; + } + + case token::type::string: + { + new(&_string._str) std::string(other._string._str); + + break; + } + + case token::type::utterance: + { + new(&_utterance._utterance) std::list(other._utterance._utterance); + + break; + } + } + return *this; } - bool verb_token::complete() const + token::~token() { - return true; + switch (_type) + { + case token::type::verb: + { + _verb._verb.~verb(); + + break; + } + + case token::type::noun: + { + _noun._noun.~noun(); + + break; + } + + case token::type::adjective: + { + _adjective._adjective.~adjective(); + + break; + } + + case token::type::adverb: + { + _adverb._adverb.~adverb(); + + break; + } + + case token::type::preposition: + { + _preposition._preposition.~preposition(); + + break; + } + + case token::type::fillin: + { + // Nothing! + + break; + } + + case token::type::string: + { + using string_type = std::string; + _string._str.~string_type(); + + break; + } + + case token::type::utterance: + { + using list_type = std::list; + _utterance._utterance.~list_type(); + + break; + } + } } - std::string verb_token::compile() const + bool token::is_complete() const { - switch (_inflection) + if (_type == token::type::utterance) { - 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(); + return std::all_of(std::begin(_utterance._utterance), std::end(_utterance._utterance), [] (const token& tkn) { + return tkn.is_complete(); + }); + } else if (_type == token::type::fillin) + { + return false; + } else { + return true; } } - token* verb_token::copy() const + std::string token::compile() const + { + switch (_type) + { + case token::type::verb: + { + switch (_verb._infl) + { + case token::verb_inflection::infinitive: return _verb._verb.infinitive_form(); + case token::verb_inflection::past_tense: return _verb._verb.past_tense_form(); + case token::verb_inflection::past_participle: return _verb._verb.past_participle_form(); + case token::verb_inflection::ing_form: return _verb._verb.ing_form(); + case token::verb_inflection::s_form: return _verb._verb.s_form(); + } + } + + case token::type::noun: + { + switch (_noun._infl) + { + case token::noun_inflection::singular: return _noun._noun.singular_form(); + case token::noun_inflection::plural: return _noun._noun.plural_form(); + } + } + + case token::type::adjective: + { + switch (_adjective._infl) + { + case token::adjective_inflection::base: return _adjective._adjective.base_form(); + case token::adjective_inflection::comparative: return _adjective._adjective.comparative_form(); + case token::adjective_inflection::superlative: return _adjective._adjective.superlative_form(); + } + } + + case token::type::adverb: + { + switch (_adverb._infl) + { + case token::adverb_inflection::base: return _adverb._adverb.base_form(); + case token::adverb_inflection::comparative: return _adverb._adverb.comparative_form(); + case token::adverb_inflection::superlative: return _adverb._adverb.superlative_form(); + } + } + + case token::type::preposition: return _preposition._preposition.get_form(); + case token::type::string: return _string._str; + + case token::type::fillin: + { + throw std::runtime_error("Cannot compile a fillin token."); + } + + case token::type::utterance: + { + std::list compiled; + std::transform(std::begin(_utterance._utterance), std::end(_utterance._utterance), std::back_inserter(compiled), [] (token tkn) { + return tkn.compile(); + }); + + return verbly::implode(std::begin(compiled), std::end(compiled), " "); + } + } + } + + token::token(verb _verb) : _type(type::verb) + { + new(&this->_verb._verb) verb(_verb); + this->_verb._infl = verb_inflection::infinitive; + } + + token::token(verb _verb, verb_inflection _infl) : token(_verb) + { + this->_verb._infl = _infl; + } + + token& token::operator=(verb _verb) + { + *this = token{_verb}; + + return *this; + } + + verb token::get_verb() const + { + assert(_type == type::verb); + + return _verb._verb; + } + + void token::set_verb(verb _verb) + { + assert(_type == type::verb); + + this->_verb._verb = _verb; + } + + token::verb_inflection token::get_verb_inflection() const + { + assert(_type == type::verb); + + return _verb._infl; + } + + void token::set_verb_inflection(verb_inflection _infl) + { + assert(_type == type::verb); + + _verb._infl = _infl; + } + + token::token(noun _noun) : _type(type::noun) + { + new(&this->_noun._noun) noun(_noun); + this->_noun._infl = noun_inflection::singular; + } + + token::token(noun _noun, noun_inflection _infl) : token(_noun) + { + this->_noun._infl = _infl; + } + + token& token::operator=(noun _noun) { - return new verb_token(*this); + *this = token{_noun}; + + return *this; + } + + noun token::get_noun() const + { + assert(_type == type::noun); + + return _noun._noun; + } + + void token::set_noun(noun _noun) + { + assert(_type == type::noun); + + this->_noun._noun = _noun; + } + + token::noun_inflection token::get_noun_inflection() const + { + assert(_type == type::noun); + + return _noun._infl; + } + + void token::set_noun_inflection(noun_inflection _infl) + { + assert(_type == type::noun); + + _noun._infl = _infl; + } + + token::token(adjective _adjective) : _type(type::adjective) + { + new(&this->_adjective._adjective) adjective(_adjective); + this->_adjective._infl = adjective_inflection::base; + } + + token::token(adjective _adjective, adjective_inflection _infl) : token(_adjective) + { + this->_adjective._infl = _infl; + } + + token& token::operator=(adjective _adjective) + { + *this = token{_adjective}; + + return *this; + } + + adjective token::get_adjective() const + { + assert(_type == type::adjective); + + return _adjective._adjective; + } + + void token::set_adjective(adjective _adjective) + { + assert(_type == type::adjective); + + this->_adjective._adjective = _adjective; + } + + token::adjective_inflection token::get_adjective_inflection() const + { + assert(_type == type::adjective); + + return _adjective._infl; + } + + void token::set_adjective_inflection(adjective_inflection _infl) + { + assert(_type == type::adjective); + + _adjective._infl = _infl; + } + + token::token(adverb _adverb) : _type(type::adverb) + { + new(&this->_adverb._adverb) adverb(_adverb); + this->_adverb._infl = adverb_inflection::base; + } + + token::token(adverb _adverb, adverb_inflection _infl) : token(_adverb) + { + this->_adverb._infl = _infl; + } + + token& token::operator=(adverb _adverb) + { + *this = token{_adverb}; + + return *this; + } + + adverb token::get_adverb() const + { + assert(_type == type::adverb); + + return _adverb._adverb; + } + + void token::set_adverb(adverb _adverb) + { + assert(_type == type::adverb); + + this->_adverb._adverb = _adverb; + } + + token::adverb_inflection token::get_adverb_inflection() const + { + assert(_type == type::adverb); + + return _adverb._infl; + } + + void token::set_adverb_inflection(adverb_inflection _infl) + { + assert(_type == type::adverb); + + _adverb._infl = _infl; + } + + token::token(preposition _preposition) : _type(type::preposition) + { + new(&this->_preposition._preposition) preposition(_preposition); + } + + token& token::operator=(preposition _preposition) + { + *this = token{_preposition}; + + return *this; + } + + preposition token::get_preposition() const + { + assert(_type == type::preposition); + + return _preposition._preposition; + } + + void token::set_preposition(preposition _preposition) + { + assert(_type == type::preposition); + + this->_preposition._preposition = _preposition; + } + + token::token(fillin_type _ft) : _type(type::fillin) + { + _fillin._type = _ft; + } + + token& token::operator=(fillin_type _ft) + { + *this = token{_ft}; + + return *this; + } + + token::fillin_type token::get_fillin_type() const + { + assert(_type == type::fillin); + + return _fillin._type; + } + + void token::set_fillin_type(fillin_type _ft) + { + assert(_type == type::fillin); + + _fillin._type = _ft; + } + + token::token() : _type(type::utterance) + { + new(&_utterance._utterance) std::list(); + } + + token::token(std::initializer_list _init) : _type(type::utterance) + { + new(&_utterance._utterance) std::list(_init); + } + + token::iterator token::begin() + { + assert(_type == type::utterance); + + return _utterance._utterance.begin(); + } + + token::iterator token::end() + { + assert(_type == type::utterance); + + return _utterance._utterance.end(); + } + + token& token::operator<<(token _tkn) + { + assert(_type == type::utterance); + + _utterance._utterance.push_back(_tkn); + + return *this; + } + + void token::push_back(token _tkn) + { + assert(_type == type::utterance); + + _utterance._utterance.push_back(_tkn); + } + + void token::insert(iterator before, token _tkn) + { + assert(_type == type::utterance); + + _utterance._utterance.insert(before, _tkn); + } + + void token::replace(iterator torepl, token _tkn) + { + assert(_type == type::utterance); + + _utterance._utterance.insert(torepl, _tkn); + _utterance._utterance.erase(torepl); + } + + void token::erase(iterator toer) + { + assert(_type == type::utterance); + + _utterance._utterance.erase(toer); + } + + token::token(std::string _str) : _type(type::string) + { + new(&_string._str) std::string(_str); + } + + token& token::operator=(std::string _str) + { + *this = token{_str}; + + return *this; + } + + std::string token::get_string() const + { + assert(_type == type::string); + + return _string._str; + } + + void token::set_string(std::string _str) + { + assert(_type == type::string); + + _string._str = _str; } }; diff --git a/lib/token.h b/lib/token.h index b22032b..788a106 100644 --- a/lib/token.h +++ b/lib/token.h @@ -1,314 +1,169 @@ #ifndef TOKEN_H_AD62C505 #define TOKEN_H_AD62C505 -#include -#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, + noun, + adjective, + adverb, + preposition, fillin, - string, - utterance + utterance, + string }; - 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 { + enum class verb_inflection { infinitive, past_tense, past_participle, - ing_form, - s_form + s_form, + ing_form }; - private: - // Verb - const verb* _verb; - inflection _inflection = inflection::infinitive; - - public: - verb_token(const verb& _verb); - - const verb& get_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())); - } - } + enum class noun_inflection { + singular, + plural + }; - utterance_token(utterance_token&& other) : token(token::type::utterance), utterance(std::move(other.utterance)) - { - - } + enum class adjective_inflection { + base, + comparative, + superlative + }; - utterance_token& operator=(const utterance_token& other) - { - utterance.clear(); - - for (auto& tkn : other.utterance) - { - utterance.push_back(std::unique_ptr(tkn->copy())); - } - - return *this; - } + enum class adverb_inflection { + base, + comparative, + superlative + }; - utterance_token& operator=(utterance_token&& other) - { - utterance = std::move(other.utterance); - - return *this; - } + enum class fillin_type { + generic, + noun_phrase, + adjective_phrase, + adverb_phrase, + participle_phrase, + infinitive_phrase + }; - iterator begin() - { - return std::begin(utterance); - } + type get_type() const; - iterator end() - { - return std::end(utterance); - } + int get_extra() const; + void set_extra(int _arg); - void erase(iterator it) - { - utterance.erase(it); - } + token(const token& other); + token& operator=(const token& other); + ~token(); - bool complete() const - { - return std::all_of(std::begin(utterance), std::end(utterance), [] (const std::unique_ptr& tkn) { - return tkn->complete(); - }); - } + bool is_complete() const; + std::string compile() const; - 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; - } + // Verb + token(verb _verb); + token(verb _verb, verb_inflection _infl); + token& operator=(verb _verb); + verb get_verb() const; + void set_verb(verb _verb); + verb_inflection get_verb_inflection() const; + void set_verb_inflection(verb_inflection _infl); + + // Noun + token(noun _noun); + token(noun _noun, noun_inflection _infl); + token& operator=(noun _noun); + noun get_noun() const; + void set_noun(noun _noun); + noun_inflection get_noun_inflection() const; + void set_noun_inflection(noun_inflection _infl); + + // Adjective + token(adjective _adjective); + token(adjective _adjective, adjective_inflection _infl); + token& operator=(adjective _adjective); + adjective get_adjective() const; + void set_adjective(adjective _adjective); + adjective_inflection get_adjective_inflection() const; + void set_adjective_inflection(adjective_inflection _infl); + + // Adverb + token(adverb _adverb); + token(adverb _adverb, adverb_inflection _infl); + token& operator=(adverb _adverb); + adverb get_adverb() const; + void set_adverb(adverb _adverb); + adverb_inflection get_adverb_inflection() const; + void set_adverb_inflection(adverb_inflection _infl); + + // Preposition + token(preposition _preposition); + token& operator=(preposition _preposition); + preposition get_preposition() const; + void set_preposition(preposition _preposition); - 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; - } + token(fillin_type _ft); + token& operator=(fillin_type _ft); + fillin_type get_fillin_type() const; + void set_fillin_type(fillin_type _ft); - std::string& theme() - { - return m_theme; - } - - fillin_type get_fillin_type() const - { - return m_fillin_type; - } - - bool complete() const - { - return false; - } - - std::string compile() const - { - return ""; - } + // Utterance + typedef std::list::iterator iterator; + + token(); + token(std::initializer_list _init); + iterator begin(); + iterator end(); + token& operator<<(token _tkn); + void push_back(token _tkn); + void insert(iterator before, token _tkn); + void replace(iterator torepl, token _tkn); + void erase(iterator toer); - 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; - } + token(std::string _str); + token& operator=(std::string _str); + std::string get_string() const; + void set_string(std::string _str); - std::string compile() const - { - return str; - } - - token* copy() const - { - return new string_token(*this); - } + private: + type _type; + int _extra = 0; + union { + struct { + verb _verb; + verb_inflection _infl; + } _verb; + struct { + noun _noun; + noun_inflection _infl; + } _noun; + struct { + adjective _adjective; + adjective_inflection _infl; + } _adjective; + struct { + adverb _adverb; + adverb_inflection _infl; + } _adverb; + struct { + preposition _preposition; + } _preposition; + struct { + fillin_type _type; + } _fillin; + struct { + std::string _str; + } _string; + struct { + std::list _utterance; + } _utterance; + }; }; - + }; #endif /* end of include guard: TOKEN_H_AD62C505 */ diff --git a/lib/util.h b/lib/util.h index 815b47c..fb5fe67 100644 --- a/lib/util.h +++ b/lib/util.h @@ -1,10 +1,6 @@ #ifndef UTIL_H_15DDCA2D #define UTIL_H_15DDCA2D -#include -#include -#include - namespace verbly { template @@ -32,7 +28,7 @@ namespace verbly { while (!input.empty()) { - int divider = input.find(" "); + int divider = input.find(delimiter); if (divider == std::string::npos) { result.push_back(input); @@ -41,7 +37,7 @@ namespace verbly { } else { result.push_back(input.substr(0, divider)); - input = input.substr(divider+1); + input = input.substr(divider+delimiter.length()); } } diff --git a/lib/verb.cpp b/lib/verb.cpp index 23f7c92..1f45d53 100644 --- a/lib/verb.cpp +++ b/lib/verb.cpp @@ -2,6 +2,11 @@ namespace verbly { + verb::verb() + { + + } + verb::verb(const data& _data, int _id) : word(_data, _id) { @@ -9,185 +14,51 @@ namespace verbly { std::string verb::base_form() const { + assert(_valid == true); + return _infinitive; } std::string verb::infinitive_form() const { + assert(_valid == true); + return _infinitive; } std::string verb::past_tense_form() const { + assert(_valid == true); + return _past_tense; } std::string verb::past_participle_form() const { + assert(_valid == true); + return _past_participle; } std::string verb::ing_form() const { + assert(_valid == true); + 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)); - } + assert(_valid == true); - return *this; + return _s_form; } - verb_query& verb_query::has_pronunciation(bool _has_prn) + frame_query verb::frames() const { - this->_has_prn = _has_prn; + assert(_valid == true); - return *this; + return _data->frames().for_verb(*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 index 7cc87e2..7a2486e 100644 --- a/lib/verb.h +++ b/lib/verb.h @@ -3,26 +3,7 @@ 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 frame_query; class verb : public word { private: @@ -35,6 +16,7 @@ namespace verbly { friend class verb_query; public: + verb(); verb(const data& _data, int _id); std::string base_form() const; @@ -43,29 +25,8 @@ namespace verbly { 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; + frame_query frames() const; }; }; diff --git a/lib/verb_query.cpp b/lib/verb_query.cpp new file mode 100644 index 0000000..173a04e --- /dev/null +++ b/lib/verb_query.cpp @@ -0,0 +1,170 @@ +#include "verbly.h" + +namespace verbly { + + 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() + { + this->_random = true; + + 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() + { + this->_has_prn = true; + + return *this; + } + + verb_query& verb_query::has_frames() + { + this->_has_frames = true; + + 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 (!_has_frames) + { + conditions.push_back("verb_id IN (SELECT verb_id FROM verb_groups)"); + } + + 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_query.h b/lib/verb_query.h new file mode 100644 index 0000000..24f5732 --- /dev/null +++ b/lib/verb_query.h @@ -0,0 +1,34 @@ +#ifndef VERB_QUERY_H_34E5A679 +#define VERB_QUERY_H_34E5A679 + +namespace verbly { + + class verb_query { + public: + verb_query(const data& _data); + + verb_query& limit(int _limit); + verb_query& random(); + verb_query& except(const verb& _word); + verb_query& rhymes_with(const word& _word); + verb_query& has_pronunciation(); + + verb_query& has_frames(); + + 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 _has_frames = false; + }; + +}; + +#endif /* end of include guard: VERB_QUERY_H_34E5A679 */ diff --git a/lib/verbly.h b/lib/verbly.h index b9f5367..cfaf5bc 100644 --- a/lib/verbly.h +++ b/lib/verbly.h @@ -1,14 +1,35 @@ #ifndef VERBLY_H_5B39CE50 #define VERBLY_H_5B39CE50 -#include "c++14.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "util.h" -#include "token.h" #include "data.h" #include "word.h" #include "verb.h" #include "adverb.h" #include "adjective.h" #include "noun.h" +#include "frame.h" +#include "preposition.h" +#include "token.h" +#include "noun_query.h" +#include "adverb_query.h" +#include "adjective_query.h" +#include "verb_query.h" +#include "frame_query.h" #endif /* end of include guard: VERBLY_H_5B39CE50 */ diff --git a/lib/word.cpp b/lib/word.cpp index 15af150..13c611f 100644 --- a/lib/word.cpp +++ b/lib/word.cpp @@ -3,13 +3,20 @@ namespace verbly { - word::word(const data& _data, int _id) : _data(_data), _id(_id) + word::word() + { + + } + + word::word(const data& _data, int _id) : _data(&_data), _id(_id), _valid(true) { } std::list word::rhyme_phonemes() const { + assert(_valid == true); + std::list result; for (auto pronunciation : pronunciations) @@ -32,6 +39,8 @@ namespace verbly { bool word::starts_with_vowel_sound() const { + assert(_valid == true); + if (pronunciations.size() > 0) { return std::any_of(std::begin(pronunciations), std::end(pronunciations), [] (std::list phonemes) { diff --git a/lib/word.h b/lib/word.h index db3242a..dc6fac8 100644 --- a/lib/word.h +++ b/lib/word.h @@ -3,26 +3,23 @@ namespace verbly { - class adjective_query; - class verb_query; - class adverb_query; - - template - class query; - class word { protected: - const data& _data; + const data* _data; int _id; + bool _valid = false; std::list> pronunciations; + word(); word(const data& _data, int _id); friend class adjective_query; friend class verb_query; friend class noun_query; friend class adverb_query; + friend class frame_query; + friend class preposition_query; public: virtual std::string base_form() const = 0; -- cgit 1.4.1