From ae5f75965f8202c8478622763a27ef1848a8ed1a Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Wed, 16 Mar 2016 11:27:16 -0400 Subject: Added more inflections, word relationships, and pronunciations Nouns, adjectives, and adverbs now have inflected forms. A large number of WordNet word relationships (all noun-noun relationships, plus synonymy and antonymy for all word types except verbs) have been added. Additionally, CMUDICT is now being used to store word pronunciations for rhyming purposes. Verbly is now also a compiled library rather than being header-only due to the complexity of the query interface. --- adjective.cpp | 586 +++++++++++++++++++++++++++++++++++++ adjective.h | 126 +++++++- adverb.cpp | 364 +++++++++++++++++++++++ adverb.h | 75 ++++- data.cpp | 50 ++++ data.h | 275 ++---------------- noun.cpp | 916 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ noun.h | 171 +++++++++++ token.cpp | 53 ++++ token.h | 82 +++--- util.h | 53 ++++ verb.cpp | 193 +++++++++++++ verb.h | 68 +++-- verbly.h | 7 +- word.cpp | 32 ++ word.h | 35 +++ 16 files changed, 2740 insertions(+), 346 deletions(-) create mode 100644 adjective.cpp create mode 100644 adverb.cpp create mode 100644 data.cpp create mode 100644 noun.cpp create mode 100644 noun.h create mode 100644 token.cpp create mode 100644 util.h create mode 100644 verb.cpp create mode 100644 word.cpp create mode 100644 word.h diff --git a/adjective.cpp b/adjective.cpp new file mode 100644 index 0000000..0f4087f --- /dev/null +++ b/adjective.cpp @@ -0,0 +1,586 @@ +#include "verbly.h" + +namespace verbly { + + adjective::adjective(const data& _data, int _id) : word(_data, _id) + { + + } + + std::string adjective::base_form() const + { + return _base_form; + } + + std::string adjective::comparative_form() const + { + return _comparative_form; + } + + std::string adjective::superlative_form() const + { + return _superlative_form; + } + + adjective::positioning adjective::position() const + { + return _position; + } + + bool adjective::has_comparative_form() const + { + return !_comparative_form.empty(); + } + + bool adjective::has_superlative_form() const + { + return !_superlative_form.empty(); + } + + bool adjective::has_position() const + { + return _position != adjective::positioning::undefined; + } + + adjective_query adjective::antonyms() const + { + return _data.adjectives().antonym_of(*this); + } + + adjective_query adjective::synonyms() const + { + return _data.adjectives().synonym_of(*this); + } + + adjective_query adjective::generalizations() const + { + return _data.adjectives().generalization_of(*this); + } + + adjective_query adjective::specifications() const + { + return _data.adjectives().specification_of(*this); + } + + noun_query adjective::anti_pertainyms() const + { + return _data.nouns().anti_pertainym_of(*this); + } + + adverb_query adjective::mannernyms() const + { + return _data.adverbs().mannernym_of(*this); + } + + noun_query adjective::attributes() const + { + return _data.nouns().attribute_of(*this); + } + + adjective_query::adjective_query(const data& _data) : _data(_data) + { + + } + + adjective_query& adjective_query::limit(int _limit) + { + if ((_limit > 0) || (_limit == unlimited)) + { + this->_limit = _limit; + } + + return *this; + } + + adjective_query& adjective_query::random(bool _random) + { + this->_random = _random; + + return *this; + } + + adjective_query& adjective_query::except(const adjective& _word) + { + _except.push_back(_word); + + return *this; + } + + adjective_query& adjective_query::rhymes_with(const word& _word) + { + for (auto rhyme : _word.rhyme_phonemes()) + { + _rhymes.push_back(rhyme); + } + + if (dynamic_cast(&_word) != nullptr) + { + _except.push_back(dynamic_cast(_word)); + } + + return *this; + } + + adjective_query& adjective_query::has_pronunciation(bool _has_prn) + { + this->_has_prn = _has_prn; + + return *this; + } + + adjective_query& adjective_query::is_variant(bool _is_variant) + { + this->_is_variant = _is_variant; + + return *this; + } + + adjective_query& adjective_query::variant_of(const noun& _noun) + { + _variant_of.push_back(_noun); + + return *this; + } + + adjective_query& adjective_query::not_variant_of(const noun& _noun) + { + _not_variant_of.push_back(_noun); + + return *this; + } + + adjective_query& adjective_query::has_antonyms(bool _is_antonymic) + { + this->_is_antonymic = _is_antonymic; + + return *this; + } + + adjective_query& adjective_query::antonym_of(const adjective& _adj) + { + _antonym_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::not_antonym_of(const adjective& _adj) + { + _not_antonym_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::has_synonyms(bool _is_synonymic) + { + this->_is_synonymic = _is_synonymic; + + return *this; + } + + adjective_query& adjective_query::synonym_of(const adjective& _adj) + { + _synonym_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::not_synonym_of(const adjective& _adj) + { + _not_synonym_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::is_generalization(bool _is_generalization) + { + this->_is_generalization = _is_generalization; + + return *this; + } + + adjective_query& adjective_query::generalization_of(const adjective& _adj) + { + _generalization_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::not_generalization_of(const adjective& _adj) + { + _not_generalization_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::is_specification(bool _is_specification) + { + this->_is_specification = _is_specification; + + return *this; + } + + adjective_query& adjective_query::specification_of(const adjective& _adj) + { + _specification_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::not_specification_of(const adjective& _adj) + { + _not_specification_of.push_back(_adj); + + return *this; + } + + adjective_query& adjective_query::is_pertainymic(bool _is_pertainymic) + { + this->_is_pertainymic = _is_pertainymic; + + return *this; + } + + adjective_query& adjective_query::pertainym_of(const noun& _noun) + { + _pertainym_of.push_back(_noun); + + return *this; + } + + adjective_query& adjective_query::is_mannernymic(bool _is_mannernymic) + { + this->_is_mannernymic = _is_mannernymic; + + return *this; + } + + adjective_query& adjective_query::anti_mannernym_of(const adverb& _adv) + { + _anti_mannernym_of.push_back(_adv); + + return *this; + } + + std::list adjective_query::run() const + { + std::stringstream construct; + construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; + std::list conditions; + + if (_has_prn) + { + conditions.push_back("adjective_id IN (SELECT adjective_id FROM adjective_pronunciations)"); + } + + if (!_rhymes.empty()) + { + std::list clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); + std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + for (auto except : _except) + { + conditions.push_back("adjective_id != @EXCID"); + } + + if (_requires_comparative_form) + { + conditions.push_back("comparative IS NOT NULL"); + } + + if (_requires_superlative_form) + { + conditions.push_back("superlative IS NOT NULL"); + } + + if (_position != adjective::positioning::undefined) + { + switch (_position) + { + case adjective::positioning::predicate: conditions.push_back("position = 'p'"); break; + case adjective::positioning::attributive: conditions.push_back("position = 'a'"); break; + case adjective::positioning::postnominal: conditions.push_back("position = 'i'"); break; + } + } + + if (_is_variant) + { + conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)"); + } + + if (!_variant_of.empty()) + { + std::list clauses(_variant_of.size(), "noun_id = @ATTRID"); + std::string cond = "adjective_id IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_variant_of.empty()) + { + std::list clauses(_not_variant_of.size(), "noun_id = @NATTRID"); + std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_antonymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); + } + + if (!_antonym_of.empty()) + { + std::list clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); + std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_antonym_of.empty()) + { + std::list clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); + std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_synonymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); + } + + if (!_synonym_of.empty()) + { + std::list clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); + std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_synonym_of.empty()) + { + std::list clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); + std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_generalization) + { + conditions.push_back("adjective_id IN (SELECT general_id FROM specification)"); + } + + if (!_generalization_of.empty()) + { + std::list clauses(_generalization_of.size(), "specific_id = @SPECID"); + std::string cond = "adjective_id IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_generalization_of.empty()) + { + std::list clauses(_not_generalization_of.size(), "specific_id = @NSPECID"); + std::string cond = "adjective_id NOT IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_specification) + { + conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)"); + } + + if (!_specification_of.empty()) + { + std::list clauses(_specification_of.size(), "general_id = @GENID"); + std::string cond = "adjective_id IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_specification_of.empty()) + { + std::list clauses(_not_specification_of.size(), "general_id = @NGENID"); + std::string cond = "adjective_id NOT IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_pertainymic) + { + conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)"); + } + + if (!_pertainym_of.empty()) + { + std::list clauses(_pertainym_of.size(), "noun_id = @APERID"); + std::string cond = "adjective_id IN (SELECT pertainym_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_mannernymic) + { + conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)"); + } + + if (!_anti_mannernym_of.empty()) + { + std::list clauses(_anti_mannernym_of.size(), "mannernym_id = @MANID"); + std::string cond = "adjective_id IN (SELECT adjective_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!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); + } + + 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/adjective.h b/adjective.h index 9d7883f..4927d59 100644 --- a/adjective.h +++ b/adjective.h @@ -3,17 +3,129 @@ namespace verbly { - class adjective { + class adjective_query; + class adverb_query; + class noun_query; + + class adjective : public word { + public: + enum class positioning { + undefined, + predicate, + attributive, + postnominal + }; + private: - int id; + std::string _base_form; + std::string _comparative_form; + std::string _superlative_form; + positioning _position = positioning::undefined; + + friend class adjective_query; + + public: + adjective(const data& _data, int _id); + + std::string base_form() const; + std::string comparative_form() const; + std::string superlative_form() const; + positioning position() const; + + bool has_comparative_form() const; + bool has_superlative_form() const; + bool has_position() const; + adjective_query antonyms() const; + adjective_query synonyms() const; + adjective_query generalizations() const; + adjective_query specifications() const; + noun_query anti_pertainyms() const; + adverb_query mannernyms() const; + noun_query attributes() const; + }; + + class adjective_query { public: - std::string form; + 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); + + 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; - adjective(int id) : id(id) - { - - } + bool _is_mannernymic = false; + std::list _anti_mannernym_of; }; }; diff --git a/adverb.cpp b/adverb.cpp new file mode 100644 index 0000000..9bb5a0d --- /dev/null +++ b/adverb.cpp @@ -0,0 +1,364 @@ +#include "verbly.h" + +namespace verbly { + + adverb::adverb(const data& _data, int _id) : word(_data, _id) + { + + } + + std::string adverb::base_form() const + { + return _base_form; + } + + std::string adverb::comparative_form() const + { + return _comparative_form; + } + + std::string adverb::superlative_form() const + { + return _superlative_form; + } + + bool adverb::has_comparative_form() const + { + return !_comparative_form.empty(); + } + + bool adverb::has_superlative_form() const + { + return !_superlative_form.empty(); + } + + adverb_query adverb::antonyms() const + { + return _data.adverbs().antonym_of(*this); + } + + adverb_query adverb::synonyms() const + { + return _data.adverbs().synonym_of(*this); + } + + adjective_query adverb::anti_mannernyms() const + { + return _data.adjectives().anti_mannernym_of(*this); + } + + adverb_query::adverb_query(const data& _data) : _data(_data) + { + + } + + adverb_query& adverb_query::limit(int _limit) + { + if ((_limit > 0) || (_limit == unlimited)) + { + this->_limit = _limit; + } + + return *this; + } + + adverb_query& adverb_query::random(bool _random) + { + this->_random = _random; + + return *this; + } + + adverb_query& adverb_query::except(const adverb& _word) + { + _except.push_back(_word); + + return *this; + } + + adverb_query& adverb_query::rhymes_with(const word& _word) + { + for (auto rhyme : _word.rhyme_phonemes()) + { + _rhymes.push_back(rhyme); + } + + if (dynamic_cast(&_word) != nullptr) + { + _except.push_back(dynamic_cast(_word)); + } + + return *this; + } + + adverb_query& adverb_query::has_pronunciation(bool _has_prn) + { + this->_has_prn = _has_prn; + + return *this; + } + + adverb_query& adverb_query::requires_comparative_form(bool _arg) + { + _requires_comparative_form = _arg; + + return *this; + } + + adverb_query& adverb_query::requires_superlative_form(bool _arg) + { + _requires_superlative_form = _arg; + + return *this; + } + + adverb_query& adverb_query::has_antonyms(bool _arg) + { + _has_antonyms = _arg; + + return *this; + } + + adverb_query& adverb_query::antonym_of(const adverb& _adv) + { + _antonym_of.push_back(_adv); + + return *this; + } + + adverb_query& adverb_query::not_antonym_of(const adverb& _adv) + { + _not_antonym_of.push_back(_adv); + + return *this; + } + + adverb_query& adverb_query::has_synonyms(bool _arg) + { + _has_synonyms = _arg; + + return *this; + } + + adverb_query& adverb_query::synonym_of(const adverb& _adv) + { + _synonym_of.push_back(_adv); + + return *this; + } + + adverb_query& adverb_query::not_synonym_of(const adverb& _adv) + { + _not_synonym_of.push_back(_adv); + + return *this; + } + + adverb_query& adverb_query::is_mannernymic(bool _arg) + { + _is_mannernymic = _arg; + + return *this; + } + + adverb_query& adverb_query::mannernym_of(const adjective& _adj) + { + _mannernym_of.push_back(_adj); + + return *this; + } + + std::list adverb_query::run() const + { + std::stringstream construct; + construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; + std::list conditions; + + if (_has_prn) + { + conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)"); + } + + if (!_rhymes.empty()) + { + std::list clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); + std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + for (auto except : _except) + { + conditions.push_back("adverb_id != @EXCID"); + } + + if (_requires_comparative_form) + { + conditions.push_back("comparative IS NOT NULL"); + } + + if (_requires_superlative_form) + { + conditions.push_back("superlative IS NOT NULL"); + } + + if (_has_antonyms) + { + conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)"); + } + + if (!_antonym_of.empty()) + { + std::list clauses(_antonym_of.size(), "adverb_1_id = @ANTID"); + std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_antonym_of.empty()) + { + std::list clauses(_not_antonym_of.size(), "adverb_1_id = @NANTID"); + std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_has_synonyms) + { + conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)"); + } + + if (!_synonym_of.empty()) + { + std::list clauses(_synonym_of.size(), "adverb_1_id = @SYNID"); + std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_synonym_of.empty()) + { + std::list clauses(_not_synonym_of.size(), "adverb_1_id = @NSYNID"); + std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_mannernymic) + { + conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)"); + } + + if (!_mannernym_of.empty()) + { + std::list clauses(_mannernym_of.size(), "adjective_id = @AMANID"); + std::string cond = "adverb_id IN (SELECT mannernym_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!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); + } + + 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/adverb.h b/adverb.h index 6d2466e..42c3492 100644 --- a/adverb.h +++ b/adverb.h @@ -3,17 +3,78 @@ namespace verbly { - class adverb { + class adverb : public word { private: - int id; + std::string _base_form; + std::string _comparative_form; + std::string _superlative_form; + friend class adverb_query; + + public: + adverb(const data& _data, int _id); + + std::string base_form() const; + std::string comparative_form() const; + std::string superlative_form() const; + + bool has_comparative_form() const; + bool has_superlative_form() const; + + adverb_query antonyms() const; + adverb_query synonyms() const; + adjective_query anti_mannernyms() const; + }; + + class adverb_query { public: - std::string form; + 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); + + 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; - adverb(int id) : id(id) - { - - } + bool _is_mannernymic = false; + std::list _mannernym_of; }; }; diff --git a/data.cpp b/data.cpp new file mode 100644 index 0000000..57a8850 --- /dev/null +++ b/data.cpp @@ -0,0 +1,50 @@ +#include "verbly.h" + +namespace verbly { + + data::data(std::string datafile) + { + if (sqlite3_open_v2(datafile.c_str(), &ppdb, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) + { + throw std::invalid_argument(sqlite3_errmsg(ppdb)); + } + } + + data::data(data&& other) + { + ppdb = other.ppdb; + } + + data& data::operator=(data&& other) + { + ppdb = other.ppdb; + + return *this; + } + + data::~data() + { + sqlite3_close_v2(ppdb); + } + + verb_query data::verbs() const + { + return verb_query(*this); + } + + adjective_query data::adjectives() const + { + return adjective_query(*this); + } + + adverb_query data::adverbs() const + { + return adverb_query(*this); + } + + noun_query data::nouns() const + { + return noun_query(*this); + } + +}; diff --git a/data.h b/data.h index e901cba..37092d7 100644 --- a/data.h +++ b/data.h @@ -1,273 +1,46 @@ #ifndef DATA_H_C4AEC3DD #define DATA_H_C4AEC3DD -#include "verb.h" #include #include namespace verbly { + class data; + class word; + class adjective; + class noun; + class verb; + class adverb; + class adjective_query; + class adverb_query; + class noun_query; + class verb_query; + class data { private: sqlite3* ppdb; - public: - class verb_query { - public: - const static int unlimited = -1; - - private: - const data& database; - int m_limit = unlimited; - bool m_random = false; - - public: - verb_query(const data& database) : database(database) - { - - } - - verb_query& limit(int m_limit) - { - if ((m_limit > 0) || (m_limit == unlimited)) - { - this->m_limit = m_limit; - } - - return *this; - } - - verb_query& random(bool m_random) - { - this->m_random = m_random; - - return *this; - } - - std::list run() const - { - std::stringstream construct; - construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; - - if (m_random) - { - construct << " ORDER BY RANDOM()"; - } - - if (m_limit != unlimited) - { - construct << " LIMIT " << m_limit; - } - - sqlite3_stmt* ppstmt; - std::string query = construct.str(); - if (sqlite3_prepare_v2(database.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) - { - throw std::runtime_error(sqlite3_errmsg(database.ppdb)); - } - - std::list output; - while (sqlite3_step(ppstmt) == SQLITE_ROW) - { - verb tnc {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); - - return output; - } - - }; - - class adjective_query { - public: - const static int unlimited = -1; - - private: - const data& database; - int m_limit = unlimited; - bool m_random = false; - - public: - adjective_query(const data& database) : database(database) - { - - } - - adjective_query& limit(int m_limit) - { - if ((m_limit > 0) || (m_limit == unlimited)) - { - this->m_limit = m_limit; - } - - return *this; - } - - adjective_query& random(bool m_random) - { - this->m_random = m_random; - - return *this; - } - - std::list run() const - { - std::stringstream construct; - construct << "SELECT adjective_id, form FROM adjectives"; - - if (m_random) - { - construct << " ORDER BY RANDOM()"; - } - - if (m_limit != unlimited) - { - construct << " LIMIT " << m_limit; - } - - sqlite3_stmt* ppstmt; - std::string query = construct.str(); - if (sqlite3_prepare_v2(database.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) - { - throw std::runtime_error(sqlite3_errmsg(database.ppdb)); - } - - std::list output; - while (sqlite3_step(ppstmt) == SQLITE_ROW) - { - adjective tnc {sqlite3_column_int(ppstmt, 0)}; - tnc.form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 1))); - - output.push_back(tnc); - } - - sqlite3_finalize(ppstmt); - - return output; - } - - }; - - class adverb_query { - public: - const static int unlimited = -1; - - private: - const data& database; - int m_limit = unlimited; - bool m_random = false; - - public: - adverb_query(const data& database) : database(database) - { - - } - - adverb_query& limit(int m_limit) - { - if ((m_limit > 0) || (m_limit == unlimited)) - { - this->m_limit = m_limit; - } - - return *this; - } - - adverb_query& random(bool m_random) - { - this->m_random = m_random; - - return *this; - } - - std::list run() const - { - std::stringstream construct; - construct << "SELECT adverb_id, form FROM adverbs"; - - if (m_random) - { - construct << " ORDER BY RANDOM()"; - } - - if (m_limit != unlimited) - { - construct << " LIMIT " << m_limit; - } - - sqlite3_stmt* ppstmt; - std::string query = construct.str(); - if (sqlite3_prepare_v2(database.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) - { - throw std::runtime_error(sqlite3_errmsg(database.ppdb)); - } - - std::list output; - while (sqlite3_step(ppstmt) == SQLITE_ROW) - { - adverb tnc {sqlite3_column_int(ppstmt, 0)}; - tnc.form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 1))); - - output.push_back(tnc); - } - - sqlite3_finalize(ppstmt); - - return output; - } - - }; + friend class adjective_query; + friend class noun_query; + friend class verb_query; + friend class adverb_query; - data(std::string datafile) - { - if (sqlite3_open_v2(datafile.c_str(), &ppdb, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) - { - throw std::invalid_argument(sqlite3_errmsg(ppdb)); - } - } + public: + data(std::string datafile); data(const data& other) = delete; data& operator=(const data& other) = delete; - data(data&& other) - { - ppdb = other.ppdb; - } - - data& operator=(data&& other) - { - ppdb = other.ppdb; - - return *this; - } - - ~data() - { - sqlite3_close_v2(ppdb); - } - - verb_query verbs() const - { - return verb_query(*this); - } + data(data&& other); + data& operator=(data&& other); - adjective_query adjectives() const - { - return adjective_query(*this); - } + ~data(); - adverb_query adverbs() const - { - return adverb_query(*this); - } + verb_query verbs() const; + adjective_query adjectives() const; + adverb_query adverbs() const; + noun_query nouns() const; }; diff --git a/noun.cpp b/noun.cpp new file mode 100644 index 0000000..9336a1c --- /dev/null +++ b/noun.cpp @@ -0,0 +1,916 @@ +#include "verbly.h" + +namespace verbly { + + noun::noun(const data& _data, int _id) : word(_data, _id) + { + + } + + std::string noun::base_form() const + { + return _singular; + } + + std::string noun::singular_form() const + { + return _singular; + } + + std::string noun::plural_form() const + { + return _plural; + } + + bool noun::has_plural_form() const + { + return !_plural.empty(); + } + + noun_query noun::hypernyms() const + { + return _data.nouns().hypernym_of(*this); + } + + noun_query noun::hyponyms() const + { + return _data.nouns().hyponym_of(*this); + } + + noun_query noun::part_meronyms() const + { + return _data.nouns().part_meronym_of(*this); + } + + noun_query noun::part_holonyms() const + { + return _data.nouns().part_holonym_of(*this); + } + + noun_query noun::substance_meronyms() const + { + return _data.nouns().substance_meronym_of(*this); + } + + noun_query noun::substance_holonyms() const + { + return _data.nouns().substance_holonym_of(*this); + } + + noun_query noun::member_meronyms() const + { + return _data.nouns().member_meronym_of(*this); + } + + noun_query noun::member_holonyms() const + { + return _data.nouns().member_holonym_of(*this); + } + + noun_query noun::classes() const + { + return _data.nouns().class_of(*this); + } + + noun_query noun::instances() const + { + return _data.nouns().instance_of(*this); + } + + noun_query noun::synonyms() const + { + return _data.nouns().synonym_of(*this); + } + + noun_query noun::antonyms() const + { + return _data.nouns().antonym_of(*this); + } + + adjective_query noun::pertainyms() const + { + return _data.adjectives().pertainym_of(*this); + } + + adjective_query noun::variations() const + { + return _data.adjectives().variant_of(*this); + } + + noun_query::noun_query(const data& _data) : _data(_data) + { + + } + + noun_query& noun_query::limit(int _limit) + { + if ((_limit > 0) || (_limit == unlimited)) + { + this->_limit = _limit; + } + + return *this; + } + + noun_query& noun_query::random(bool _random) + { + this->_random = _random; + + return *this; + } + + noun_query& noun_query::except(const noun& _word) + { + _except.push_back(_word); + + return *this; + } + + noun_query& noun_query::rhymes_with(const word& _word) + { + for (auto rhyme : _word.rhyme_phonemes()) + { + _rhymes.push_back(rhyme); + } + + if (dynamic_cast(&_word) != nullptr) + { + _except.push_back(dynamic_cast(_word)); + } + + return *this; + } + + noun_query& noun_query::has_pronunciation(bool _has_prn) + { + this->_has_prn = _has_prn; + + return *this; + } + + noun_query& noun_query::is_hypernym(bool _arg) + { + _is_hypernym = _arg; + + return *this; + } + + noun_query& noun_query::hypernym_of(const noun& _noun) + { + _hypernym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_hypernym_of(const noun& _noun) + { + _not_hypernym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_hyponym(bool _arg) + { + _is_hyponym = _arg; + + return *this; + } + + noun_query& noun_query::hyponym_of(const noun& _noun) + { + _hyponym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_hyponym_of(const noun& _noun) + { + _not_hyponym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_part_meronym(bool _arg) + { + _is_part_meronym = _arg; + + return *this; + } + + noun_query& noun_query::part_meronym_of(const noun& _noun) + { + _part_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_part_meronym_of(const noun& _noun) + { + _not_part_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_part_holonym(bool _arg) + { + _is_part_holonym = _arg; + + return *this; + } + + noun_query& noun_query::part_holonym_of(const noun& _noun) + { + _part_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_part_holonym_of(const noun& _noun) + { + _not_part_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_substance_meronym(bool _arg) + { + _is_substance_meronym = _arg; + + return *this; + } + + noun_query& noun_query::substance_meronym_of(const noun& _noun) + { + _substance_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_substance_meronym_of(const noun& _noun) + { + _not_substance_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_substance_holonym(bool _arg) + { + _is_substance_holonym = _arg; + + return *this; + } + + noun_query& noun_query::substance_holonym_of(const noun& _noun) + { + _substance_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_substance_holonym_of(const noun& _noun) + { + _not_substance_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_member_meronym(bool _arg) + { + _is_member_meronym = _arg; + + return *this; + } + + noun_query& noun_query::member_meronym_of(const noun& _noun) + { + _member_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_member_meronym_of(const noun& _noun) + { + _not_member_meronym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_member_holonym(bool _arg) + { + _is_member_holonym = _arg; + + return *this; + } + + noun_query& noun_query::member_holonym_of(const noun& _noun) + { + _member_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_member_holonym_of(const noun& _noun) + { + _not_member_holonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_proper(bool _arg) + { + _is_proper = _arg; + + return *this; + } + + noun_query& noun_query::instance_of(const noun& _noun) + { + _instance_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_instance_of(const noun& _noun) + { + _not_instance_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::is_class(bool _arg) + { + _is_class = _arg; + + return *this; + } + + noun_query& noun_query::class_of(const noun& _noun) + { + _class_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_class_of(const noun& _noun) + { + _not_class_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::has_synonyms(bool _arg) + { + _has_synonyms = _arg; + + return *this; + } + + noun_query& noun_query::synonym_of(const noun& _noun) + { + _synonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_synonym_of(const noun& _noun) + { + _not_synonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::has_antonyms(bool _arg) + { + _has_antonyms = _arg; + + return *this; + } + + noun_query& noun_query::antonym_of(const noun& _noun) + { + _antonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::not_antonym_of(const noun& _noun) + { + _not_antonym_of.push_back(_noun); + + return *this; + } + + noun_query& noun_query::has_pertainym(bool _arg) + { + _has_pertainym = _arg; + + return *this; + } + + noun_query& noun_query::anti_pertainym_of(const adjective& _adj) + { + _anti_pertainym_of.push_back(_adj); + + return *this; + } + + noun_query& noun_query::is_attribute(bool _arg) + { + _is_attribute = _arg; + + return *this; + } + + noun_query& noun_query::attribute_of(const adjective& _adj) + { + _attribute_of.push_back(_adj); + + return *this; + } + + std::list noun_query::run() const + { + std::stringstream construct; + construct << "SELECT noun_id, singular, plural FROM nouns"; + std::list conditions; + + if (_has_prn) + { + conditions.push_back("noun_id IN (SELECT noun_id FROM noun_pronunciations)"); + } + + if (!_rhymes.empty()) + { + std::list clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); + std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + for (auto except : _except) + { + conditions.push_back("noun_id != @EXCID"); + } + + if (_is_hypernym) + { + conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)"); + } + + if (!_hypernym_of.empty()) + { + std::list clauses(_hypernym_of.size(), "hyponym_id = @HYPO"); + std::string cond = "noun_id IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_hypernym_of.empty()) + { + std::list clauses(_not_hypernym_of.size(), "hyponym_id = @NHYPO"); + std::string cond = "noun_id NOT IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_hyponym) + { + conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)"); + } + + if (!_hyponym_of.empty()) + { + std::list clauses(_hyponym_of.size(), "hypernym_id = @HYPER"); + std::string cond = "noun_id IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_hyponym_of.empty()) + { + std::list clauses(_not_hyponym_of.size(), "hypernym_id = @NHYPER"); + std::string cond = "noun_id NOT IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_part_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)"); + } + + if (!_part_meronym_of.empty()) + { + std::list clauses(_part_meronym_of.size(), "holonym_id = @PHOLO"); + std::string cond = "noun_id IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_part_meronym_of.empty()) + { + std::list clauses(_not_part_meronym_of.size(), "holonym_id = @NPHOLO"); + std::string cond = "noun_id NOT IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_part_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)"); + } + + if (!_part_holonym_of.empty()) + { + std::list clauses(_part_holonym_of.size(), "meronym_id = @PMERO"); + std::string cond = "noun_id IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_part_holonym_of.empty()) + { + std::list clauses(_not_part_holonym_of.size(), "meronym_id = @NPMERO"); + std::string cond = "noun_id NOT IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_substance_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)"); + } + + if (!_substance_meronym_of.empty()) + { + std::list clauses(_substance_meronym_of.size(), "holonym_id = @SHOLO"); + std::string cond = "noun_id IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_substance_meronym_of.empty()) + { + std::list clauses(_not_substance_meronym_of.size(), "holonym_id = @NSHOLO"); + std::string cond = "noun_id NOT IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_substance_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)"); + } + + if (!_substance_holonym_of.empty()) + { + std::list clauses(_substance_holonym_of.size(), "meronym_id = @SMERO"); + std::string cond = "noun_id IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_substance_holonym_of.empty()) + { + std::list clauses(_not_substance_holonym_of.size(), "meronym_id = @NSMERO"); + std::string cond = "noun_id NOT IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_member_meronym) + { + conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)"); + } + + if (!_member_meronym_of.empty()) + { + std::list clauses(_member_meronym_of.size(), "holonym_id = @MHOLO"); + std::string cond = "noun_id IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_member_meronym_of.empty()) + { + std::list clauses(_not_member_meronym_of.size(), "holonym_id = @NMHOLO"); + std::string cond = "noun_id NOT IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_member_holonym) + { + conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)"); + } + + if (!_member_holonym_of.empty()) + { + std::list clauses(_member_holonym_of.size(), "meronym_id = @MMERO"); + std::string cond = "noun_id IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (!_not_member_holonym_of.empty()) + { + std::list clauses(_not_member_holonym_of.size(), "meronym_id = @NMMERO"); + std::string cond = "noun_id NOT IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + if (_is_proper) + { + conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)"); + } + + if (!_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 (!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); + } + + 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/noun.h b/noun.h new file mode 100644 index 0000000..f5ba256 --- /dev/null +++ b/noun.h @@ -0,0 +1,171 @@ +#ifndef NOUN_H_24A03C83 +#define NOUN_H_24A03C83 + +namespace verbly { + + class noun : public word { + private: + std::string _singular; + std::string _plural; + + friend class noun_query; + + public: + noun(const data& _data, int _id); + + std::string base_form() const; + std::string singular_form() const; + std::string plural_form() const; + + bool has_plural_form() const; + + noun_query hypernyms() const; + noun_query hyponyms() const; + noun_query part_meronyms() const; + noun_query part_holonyms() const; + noun_query substance_meronyms() const; + noun_query substance_holonyms() const; + noun_query member_meronyms() const; + noun_query member_holonyms() const; + noun_query classes() const; + noun_query instances() const; + noun_query synonyms() const; + noun_query antonyms() const; + adjective_query pertainyms() const; + adjective_query variations() const; + }; + + class noun_query { + public: + noun_query(const data& _data); + + noun_query& limit(int _limit); + noun_query& random(bool _random); + noun_query& except(const noun& _word); + noun_query& rhymes_with(const word& _word); + noun_query& has_pronunciation(bool _has_prn); + + noun_query& is_hypernym(bool _arg); + noun_query& hypernym_of(const noun& _noun); + noun_query& not_hypernym_of(const noun& _noun); + + noun_query& is_hyponym(bool _arg); + noun_query& hyponym_of(const noun& _noun); + noun_query& not_hyponym_of(const noun& _noun); + + noun_query& is_part_meronym(bool _arg); + noun_query& part_meronym_of(const noun& _noun); + noun_query& not_part_meronym_of(const noun& _noun); + + noun_query& is_part_holonym(bool _arg); + noun_query& part_holonym_of(const noun& _noun); + noun_query& not_part_holonym_of(const noun& _noun); + + noun_query& is_substance_meronym(bool _arg); + noun_query& substance_meronym_of(const noun& _noun); + noun_query& not_substance_meronym_of(const noun& _noun); + + noun_query& is_substance_holonym(bool _arg); + noun_query& substance_holonym_of(const noun& _noun); + noun_query& not_substance_holonym_of(const noun& _noun); + + noun_query& is_member_meronym(bool _arg); + noun_query& member_meronym_of(const noun& _noun); + noun_query& not_member_meronym_of(const noun& _noun); + + noun_query& is_member_holonym(bool _arg); + noun_query& member_holonym_of(const noun& _noun); + noun_query& not_member_holonym_of(const noun& _noun); + + noun_query& is_proper(bool _arg); + noun_query& 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); + + 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; + 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; + }; + +}; + +#endif /* end of include guard: NOUN_H_24A03C83 */ diff --git a/token.cpp b/token.cpp new file mode 100644 index 0000000..aa8f50e --- /dev/null +++ b/token.cpp @@ -0,0 +1,53 @@ +#include "verbly.h" + +namespace verbly { + + token::token(token::type _type) : _type(_type) + { + + } + + token::type token::token_type() const + { + return _type; + } + + verb_token::verb_token(const class verb& _verb) : token(token::type::verb), _verb(&_verb) + { + + } + + const class verb& verb_token::verb() const + { + return *_verb; + } + + verb_token& verb_token::inflect(verb_token::inflection infl) + { + _inflection = infl; + return *this; + } + + bool verb_token::complete() const + { + return true; + } + + std::string verb_token::compile() const + { + switch (_inflection) + { + case inflection::infinitive: return _verb->infinitive_form(); + case inflection::past_tense: return _verb->past_tense_form(); + case inflection::past_participle: return _verb->past_participle_form(); + case inflection::ing_form: return _verb->ing_form(); + case inflection::s_form: return _verb->s_form(); + } + } + + token* verb_token::copy() const + { + return new verb_token(*this); + } + +}; diff --git a/token.h b/token.h index 2848fd0..44d99cb 100644 --- a/token.h +++ b/token.h @@ -4,16 +4,10 @@ #include #include #include -#include "verb.h" namespace verbly { - enum class type { - verb, - fillin, - string, - utterance - }; + class verb; class selrestr { }; @@ -29,20 +23,22 @@ namespace verbly { }; class token { + public: + enum class type { + verb, + fillin, + string, + utterance + }; + protected: // General - type type; + type _type; - token(enum type type) : type(type) - { - - } + token(type _type); public: - enum type token_type() const - { - return type; - } + enum type token_type() const; virtual bool complete() const = 0; virtual std::string compile() const = 0; @@ -50,42 +46,32 @@ namespace verbly { }; class verb_token : public token { + public: + enum class inflection { + infinitive, + past_tense, + past_participle, + ing_form, + s_form + }; + private: // Verb - const verb* m_verb; - conjugation verb_infl = conjugation::infinitive; + const verb* _verb; + inflection _inflection = inflection::infinitive; public: - verb_token(const class verb& verb) : token(type::verb), m_verb(&verb) - { - - } + verb_token(const class verb& _verb); - const class verb& verb() const - { - return *m_verb; - } + const class verb& verb() const; - verb_token& conjugate(conjugation infl) - { - verb_infl = infl; - return *this; - } + verb_token& inflect(inflection infl); - bool complete() const - { - return true; - } + bool complete() const; - std::string compile() const - { - return m_verb->conjugate(verb_infl); - } + std::string compile() const; - token* copy() const - { - return new verb_token(*this); - } + token* copy() const; }; class utterance_token : public token { @@ -140,7 +126,7 @@ namespace verbly { } };*/ - utterance_token(std::initializer_list tkns) : token(type::utterance) + utterance_token(std::initializer_list tkns) : token(token::type::utterance) { for (auto tkn : tkns) { @@ -148,7 +134,7 @@ namespace verbly { } } - utterance_token(const utterance_token& other) : token(type::utterance) + utterance_token(const utterance_token& other) : token(token::type::utterance) { for (auto& tkn : other.utterance) { @@ -156,7 +142,7 @@ namespace verbly { } } - utterance_token(utterance_token&& other) : token(type::utterance), utterance(std::move(other.utterance)) + utterance_token(utterance_token&& other) : token(token::type::utterance), utterance(std::move(other.utterance)) { } @@ -237,7 +223,7 @@ namespace verbly { fillin_type m_fillin_type; public: - fillin_token(fillin_type ft) : token(type::fillin), m_fillin_type(ft) + fillin_token(fillin_type ft) : token(token::type::fillin), m_fillin_type(ft) { } @@ -301,7 +287,7 @@ namespace verbly { std::string str; public: - string_token(std::string str) : token(type::string), str(str) + string_token(std::string str) : token(token::type::string), str(str) { } diff --git a/util.h b/util.h new file mode 100644 index 0000000..815b47c --- /dev/null +++ b/util.h @@ -0,0 +1,53 @@ +#ifndef UTIL_H_15DDCA2D +#define UTIL_H_15DDCA2D + +#include +#include +#include + +namespace verbly { + + template + std::string implode(InputIterator first, InputIterator last, std::string delimiter) + { + std::stringstream result; + + for (InputIterator it = first; it != last; it++) + { + if (it != first) + { + result << delimiter; + } + + result << *it; + } + + return result.str(); + } + + template + Container split(std::string input, std::string delimiter) + { + Container result; + + while (!input.empty()) + { + int divider = input.find(" "); + if (divider == std::string::npos) + { + result.push_back(input); + + input = ""; + } else { + result.push_back(input.substr(0, divider)); + + input = input.substr(divider+1); + } + } + + return result; + } + +}; + +#endif /* end of include guard: UTIL_H_15DDCA2D */ diff --git a/verb.cpp b/verb.cpp new file mode 100644 index 0000000..23f7c92 --- /dev/null +++ b/verb.cpp @@ -0,0 +1,193 @@ +#include "verbly.h" + +namespace verbly { + + verb::verb(const data& _data, int _id) : word(_data, _id) + { + + } + + std::string verb::base_form() const + { + return _infinitive; + } + + std::string verb::infinitive_form() const + { + return _infinitive; + } + + std::string verb::past_tense_form() const + { + return _past_tense; + } + + std::string verb::past_participle_form() const + { + return _past_participle; + } + + std::string verb::ing_form() const + { + return _ing_form; + } + + std::string verb::s_form() const + { + return _s_form; + } + + verb_query::verb_query(const data& _data) : _data(_data) + { + + } + + verb_query& verb_query::limit(int _limit) + { + if ((_limit > 0) || (_limit == unlimited)) + { + this->_limit = _limit; + } + + return *this; + } + + verb_query& verb_query::random(bool _random) + { + this->_random = _random; + + return *this; + } + + verb_query& verb_query::except(const verb& _word) + { + _except.push_back(_word); + + return *this; + } + + verb_query& verb_query::rhymes_with(const word& _word) + { + for (auto rhyme : _word.rhyme_phonemes()) + { + _rhymes.push_back(rhyme); + } + + if (dynamic_cast(&_word) != nullptr) + { + _except.push_back(dynamic_cast(_word)); + } + + return *this; + } + + verb_query& verb_query::has_pronunciation(bool _has_prn) + { + this->_has_prn = _has_prn; + + return *this; + } + + std::list verb_query::run() const + { + std::stringstream construct; + construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; + std::list conditions; + + if (_has_prn) + { + conditions.push_back("verb_id IN (SELECT verb_id FROM verb_pronunciations)"); + } + + if (!_rhymes.empty()) + { + std::list clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); + std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; + conditions.push_back(cond); + } + + for (auto except : _except) + { + conditions.push_back("verb_id != @EXCID"); + } + + if (!conditions.empty()) + { + construct << " WHERE "; + construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); + } + + if (_random) + { + construct << " ORDER BY RANDOM()"; + } + + if (_limit != unlimited) + { + construct << " LIMIT " << _limit; + } + + sqlite3_stmt* ppstmt; + std::string query = construct.str(); + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + if (!_rhymes.empty()) + { + int i = 0; + for (auto rhyme : _rhymes) + { + std::string rhymer = "%" + rhyme; + sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); + + i++; + } + } + + for (auto except : _except) + { + sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); + } + + std::list output; + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + verb tnc {_data, sqlite3_column_int(ppstmt, 0)}; + tnc._infinitive = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 1))); + tnc._past_tense = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 2))); + tnc._past_participle = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 3))); + tnc._ing_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 4))); + tnc._s_form = std::string(reinterpret_cast(sqlite3_column_text(ppstmt, 5))); + + output.push_back(tnc); + } + + sqlite3_finalize(ppstmt); + + for (auto& verb : output) + { + query = "SELECT pronunciation FROM verb_pronunciations WHERE verb_id = ?"; + if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) + { + throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); + } + + sqlite3_bind_int(ppstmt, 1, verb._id); + + while (sqlite3_step(ppstmt) == SQLITE_ROW) + { + std::string pronunciation(reinterpret_cast(sqlite3_column_text(ppstmt, 0))); + auto phonemes = verbly::split>(pronunciation, " "); + + verb.pronunciations.push_back(phonemes); + } + + sqlite3_finalize(ppstmt); + } + + return output; + } + +}; diff --git a/verb.h b/verb.h index 42c8dc2..7cc87e2 100644 --- a/verb.h +++ b/verb.h @@ -1,8 +1,6 @@ #ifndef VERB_H_BCC929AD #define VERB_H_BCC929AD -#include - namespace verbly { /*class frame_part { @@ -26,42 +24,50 @@ namespace verbly { } };*/ - enum class conjugation { - present_participle, - past_participle, - infinitive - }; - - class verb { + class verb : public word { private: - int id; + std::string _infinitive; + std::string _past_tense; + std::string _past_participle; + std::string _ing_form; + std::string _s_form; + + friend class verb_query; public: - verb(int id) : id(id) - { - - } + verb(const data& _data, int _id); - std::string infinitive; - std::string past_tense; - std::string past_participle; - std::string ing_form; - std::string s_form; - //std::vector frames; + std::string base_form() const; + std::string infinitive_form() const; + std::string past_tense_form() const; + std::string past_participle_form() const; + std::string ing_form() const; + std::string s_form() const; + }; + + class verb_query { + public: + verb_query(const data& _data); - std::string conjugate(conjugation infl) const - { - switch (infl) - { - case conjugation::infinitive: return infinitive; - case conjugation::past_participle: return past_participle; - case conjugation::present_participle: return ing_form; - } - } + 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; }; }; -#include "token.h" - #endif /* end of include guard: VERB_H_BCC929AD */ diff --git a/verbly.h b/verbly.h index 44fd3a8..b9f5367 100644 --- a/verbly.h +++ b/verbly.h @@ -2,10 +2,13 @@ #define VERBLY_H_5B39CE50 #include "c++14.h" +#include "util.h" #include "token.h" +#include "data.h" +#include "word.h" #include "verb.h" -#include "adjective.h" #include "adverb.h" -#include "data.h" +#include "adjective.h" +#include "noun.h" #endif /* end of include guard: VERBLY_H_5B39CE50 */ diff --git a/word.cpp b/word.cpp new file mode 100644 index 0000000..c50e7d3 --- /dev/null +++ b/word.cpp @@ -0,0 +1,32 @@ +#include "verbly.h" + +namespace verbly { + + word::word(const data& _data, int _id) : _data(_data), _id(_id) + { + + } + + std::list word::rhyme_phonemes() const + { + std::list result; + + for (auto pronunciation : pronunciations) + { + auto phemstrt = std::find_if(std::begin(pronunciation), std::end(pronunciation), [] (std::string phoneme) { + return phoneme.find("1") != std::string::npos; + }); + + std::stringstream rhymer; + for (auto it = phemstrt; it != std::end(pronunciation); it++) + { + rhymer << " " << *it; + } + + result.push_back(rhymer.str()); + } + + return result; + } + +}; diff --git a/word.h b/word.h new file mode 100644 index 0000000..23ddb2b --- /dev/null +++ b/word.h @@ -0,0 +1,35 @@ +#ifndef WORD_H_8FC89498 +#define WORD_H_8FC89498 + +namespace verbly { + + class adjective_query; + class verb_query; + class adverb_query; + + template + class query; + + class word { + protected: + const data& _data; + int _id; + + std::list> pronunciations; + + word(const data& _data, int _id); + + friend class adjective_query; + friend class verb_query; + friend class noun_query; + friend class adverb_query; + + public: + virtual std::string base_form() const = 0; + + std::list rhyme_phonemes() const; + }; + +}; + +#endif /* end of include guard: WORD_H_8FC89498 */ -- cgit 1.4.1