diff options
40 files changed, 6363 insertions, 2853 deletions
| diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..44fa617 --- /dev/null +++ b/.gitmodules | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | [submodule "vendor/json"] | ||
| 2 | path = vendor/json | ||
| 3 | url = https://github.com/nlohmann/json | ||
| diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a3e526..c0b5dc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -4,6 +4,7 @@ project (verbly) | |||
| 4 | find_package(PkgConfig) | 4 | find_package(PkgConfig) |
| 5 | pkg_check_modules(sqlite3 sqlite3 REQUIRED) | 5 | pkg_check_modules(sqlite3 sqlite3 REQUIRED) |
| 6 | 6 | ||
| 7 | add_library(verbly lib/data.cpp lib/adjective.cpp lib/noun.cpp lib/verb.cpp lib/adverb.cpp lib/token.cpp lib/word.cpp) | 7 | include_directories(vendor/json/src) |
| 8 | add_library(verbly lib/data.cpp lib/adjective.cpp lib/noun.cpp lib/verb.cpp lib/adverb.cpp lib/token.cpp lib/word.cpp lib/frame.cpp lib/preposition.cpp lib/adjective_query.cpp lib/adverb_query.cpp lib/noun_query.cpp lib/verb_query.cpp lib/frame_query.cpp) | ||
| 8 | set_property(TARGET verbly PROPERTY CXX_STANDARD 11) | 9 | set_property(TARGET verbly PROPERTY CXX_STANDARD 11) |
| 9 | set_property(TARGET verbly PROPERTY CXX_STANDARD_REQUIRED ON) | 10 | set_property(TARGET verbly PROPERTY CXX_STANDARD_REQUIRED ON) |
| diff --git a/LICENSE b/LICENSE index 68de0ce..ad40f03 100644 --- a/LICENSE +++ b/LICENSE | |||
| @@ -72,3 +72,51 @@ purpose is completely unrestricted. If you make use of or | |||
| 72 | redistribute this material we request that you acknowledge its | 72 | redistribute this material we request that you acknowledge its |
| 73 | origin in your descriptions, as per the license information included | 73 | origin in your descriptions, as per the license information included |
| 74 | in the dictionary file (a Simplified BSD lincense). | 74 | in the dictionary file (a Simplified BSD lincense). |
| 75 | |||
| 76 | VerbNet v3.2 | ||
| 77 | ============ | ||
| 78 | VerbNet 3.0 License (also applies to VerbNet 3.X versions) | ||
| 79 | |||
| 80 | This software and database is being provided to you, the LICENSEE, by | ||
| 81 | the University of Colorado under the following license. By obtaining, using | ||
| 82 | and/or copying this software and database, you agree that you have | ||
| 83 | read, understood, and will comply with these terms and conditions.: | ||
| 84 | |||
| 85 | Permission to use, copy, modify and distribute this software and | ||
| 86 | database and its documentation for any purpose and without fee or | ||
| 87 | royalty is hereby granted, provided that you agree to comply with | ||
| 88 | the following copyright notice and statements, including the disclaimer, | ||
| 89 | and that the same appear on ALL copies of the software, database and | ||
| 90 | documentation, including modifications that you make for internal | ||
| 91 | use or for distribution. | ||
| 92 | |||
| 93 | VerbNet 3.0 (or 3.X) Copyright 2009 by University of Colorado. All rights reserved. | ||
| 94 | |||
| 95 | THIS SOFTWARE AND DATABASE IS PROVIDED "AS IS" AND THE UNIVERSITY | ||
| 96 | OF COLORADO MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR | ||
| 97 | IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, UNIVERSITY | ||
| 98 | OF COLORADO MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANT- | ||
| 99 | ABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE | ||
| 100 | OF THE LICENSED SOFTWARE, DATABASE OR DOCUMENTATION WILL NOT | ||
| 101 | INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR | ||
| 102 | OTHER RIGHTS. | ||
| 103 | |||
| 104 | The name of University of Colorado or CU may not be used in | ||
| 105 | advertising or publicity pertaining to distribution of the software | ||
| 106 | and/or database. Title to copyright in this software, database and | ||
| 107 | any associated documentation shall at all times remain with | ||
| 108 | University of Colorado and LICENSEE agrees to preserve same. | ||
| 109 | |||
| 110 | Please reference the following document(s) in any description of | ||
| 111 | applications based on VerbNet 3.0 or 3.X: | ||
| 112 | |||
| 113 | Karin Kipper, Anna Korhonen, Neville Ryant, Martha Palmer, | ||
| 114 | A Large-scale Classification of English Verbs, | ||
| 115 | Language Resources and Evaluation Journal, 42(1), pp. 21-40, | ||
| 116 | Springer Netherland, 2008. | ||
| 117 | |||
| 118 | and/or | ||
| 119 | |||
| 120 | Karin Kipper Schuler, Anna Korhonen, Susan W. Brown, VerbNet overview, | ||
| 121 | extensions, mappings and apps, Tutorial, NAACL-HLT 2009, Boulder, | ||
| 122 | Colorado. \ No newline at end of file | ||
| diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt index bbc3c4f..552526d 100644 --- a/generator/CMakeLists.txt +++ b/generator/CMakeLists.txt | |||
| @@ -5,7 +5,7 @@ find_package(PkgConfig) | |||
| 5 | pkg_check_modules(sqlite3 sqlite3 REQUIRED) | 5 | pkg_check_modules(sqlite3 sqlite3 REQUIRED) |
| 6 | find_package(libxml2 REQUIRED) | 6 | find_package(libxml2 REQUIRED) |
| 7 | 7 | ||
| 8 | include_directories(${sqlite3_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) | 8 | include_directories(${sqlite3_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR} ../vendor/json/src) |
| 9 | add_executable(generator generator.cpp) | 9 | add_executable(generator generator.cpp) |
| 10 | set_property(TARGET generator PROPERTY CXX_STANDARD 11) | 10 | set_property(TARGET generator PROPERTY CXX_STANDARD 11) |
| 11 | set_property(TARGET generator PROPERTY CXX_STANDARD_REQUIRED ON) | 11 | set_property(TARGET generator PROPERTY CXX_STANDARD_REQUIRED ON) |
| diff --git a/generator/generator.cpp b/generator/generator.cpp index 7ec94df..aea750c 100644 --- a/generator/generator.cpp +++ b/generator/generator.cpp | |||
| @@ -11,36 +11,75 @@ | |||
| 11 | #include <regex> | 11 | #include <regex> |
| 12 | #include <list> | 12 | #include <list> |
| 13 | #include <algorithm> | 13 | #include <algorithm> |
| 14 | #include <json.hpp> | ||
| 14 | #include "progress.h" | 15 | #include "progress.h" |
| 16 | #include "../lib/util.h" | ||
| 15 | 17 | ||
| 16 | struct verb { | 18 | using json = nlohmann::json; |
| 19 | |||
| 20 | struct verb_t { | ||
| 17 | std::string infinitive; | 21 | std::string infinitive; |
| 18 | std::string past_tense; | 22 | std::string past_tense; |
| 19 | std::string past_participle; | 23 | std::string past_participle; |
| 20 | std::string ing_form; | 24 | std::string ing_form; |
| 21 | std::string s_form; | 25 | std::string s_form; |
| 26 | int id; | ||
| 22 | }; | 27 | }; |
| 23 | 28 | ||
| 24 | struct adjective { | 29 | struct adjective_t { |
| 25 | std::string base; | 30 | std::string base; |
| 26 | std::string comparative; | 31 | std::string comparative; |
| 27 | std::string superlative; | 32 | std::string superlative; |
| 28 | }; | 33 | }; |
| 29 | 34 | ||
| 30 | struct noun { | 35 | struct noun_t { |
| 31 | std::string singular; | 36 | std::string singular; |
| 32 | std::string plural; | 37 | std::string plural; |
| 33 | }; | 38 | }; |
| 34 | 39 | ||
| 35 | struct group { | 40 | struct selrestr_t { |
| 41 | enum class type_t { | ||
| 42 | singleton, | ||
| 43 | andlogic, | ||
| 44 | orlogic, | ||
| 45 | empty | ||
| 46 | }; | ||
| 47 | type_t type; | ||
| 48 | std::string restriction; | ||
| 49 | bool pos; | ||
| 50 | std::list<selrestr_t> subordinates; | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct framepart_t { | ||
| 54 | enum class type_t { | ||
| 55 | np, | ||
| 56 | v, | ||
| 57 | pp, | ||
| 58 | adj, | ||
| 59 | adv, | ||
| 60 | lex | ||
| 61 | }; | ||
| 62 | type_t type; | ||
| 63 | std::string role; | ||
| 64 | selrestr_t selrestrs; | ||
| 65 | std::set<std::string> preprestrs; | ||
| 66 | std::set<std::string> synrestrs; | ||
| 67 | std::list<std::string> choices; | ||
| 68 | std::string lexval; | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct group_t { | ||
| 36 | std::string id; | 72 | std::string id; |
| 73 | std::string parent; | ||
| 37 | std::set<std::string> members; | 74 | std::set<std::string> members; |
| 75 | std::map<std::string, selrestr_t> roles; | ||
| 76 | std::list<std::list<framepart_t>> frames; | ||
| 38 | }; | 77 | }; |
| 39 | 78 | ||
| 40 | std::map<std::string, group> groups; | 79 | std::map<std::string, group_t> groups; |
| 41 | std::map<std::string, verb> verbs; | 80 | std::map<std::string, verb_t> verbs; |
| 42 | std::map<std::string, adjective> adjectives; | 81 | std::map<std::string, adjective_t> adjectives; |
| 43 | std::map<std::string, noun> nouns; | 82 | std::map<std::string, noun_t> nouns; |
| 44 | std::map<int, std::map<int, int>> wn; | 83 | std::map<int, std::map<int, int>> wn; |
| 45 | std::map<std::string, std::set<std::string>> pronunciations; | 84 | std::map<std::string, std::set<std::string>> pronunciations; |
| 46 | 85 | ||
| @@ -59,15 +98,97 @@ void print_usage() | |||
| 59 | exit(1); | 98 | exit(1); |
| 60 | } | 99 | } |
| 61 | 100 | ||
| 62 | void db_error(sqlite3* ppdb, std::string) | 101 | void db_error(sqlite3* ppdb, std::string query) |
| 63 | { | 102 | { |
| 64 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 103 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; |
| 104 | std::cout << query << std::endl; | ||
| 65 | sqlite3_close_v2(ppdb); | 105 | sqlite3_close_v2(ppdb); |
| 66 | print_usage(); | 106 | print_usage(); |
| 67 | } | 107 | } |
| 68 | 108 | ||
| 69 | /* | 109 | json export_selrestrs(selrestr_t r) |
| 70 | void parse_group(xmlNodePtr top, std::string filename) | 110 | { |
| 111 | if (r.type == selrestr_t::type_t::empty) | ||
| 112 | { | ||
| 113 | return {}; | ||
| 114 | } else if (r.type == selrestr_t::type_t::singleton) | ||
| 115 | { | ||
| 116 | json result; | ||
| 117 | result["type"] = r.restriction; | ||
| 118 | result["pos"] = r.pos; | ||
| 119 | return result; | ||
| 120 | } else { | ||
| 121 | json result; | ||
| 122 | if (r.type == selrestr_t::type_t::andlogic) | ||
| 123 | { | ||
| 124 | result["logic"] = "and"; | ||
| 125 | } else { | ||
| 126 | result["logic"] = "or"; | ||
| 127 | } | ||
| 128 | |||
| 129 | std::list<json> outlist; | ||
| 130 | std::transform(std::begin(r.subordinates), std::end(r.subordinates), std::back_inserter(outlist), &export_selrestrs); | ||
| 131 | result["children"] = outlist; | ||
| 132 | |||
| 133 | return result; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | selrestr_t parse_selrestrs(xmlNodePtr top, std::string filename) | ||
| 138 | { | ||
| 139 | selrestr_t r; | ||
| 140 | xmlChar* key; | ||
| 141 | |||
| 142 | if (!xmlStrcmp(top->name, (const xmlChar*) "SELRESTRS")) | ||
| 143 | { | ||
| 144 | if (xmlChildElementCount(top) == 0) | ||
| 145 | { | ||
| 146 | r.type = selrestr_t::type_t::empty; | ||
| 147 | } else if (xmlChildElementCount(top) == 1) | ||
| 148 | { | ||
| 149 | r = parse_selrestrs(xmlFirstElementChild(top), filename); | ||
| 150 | } else { | ||
| 151 | r.type = selrestr_t::type_t::andlogic; | ||
| 152 | |||
| 153 | if (xmlHasProp(top, (const xmlChar*) "logic")) | ||
| 154 | { | ||
| 155 | key = xmlGetProp(top, (const xmlChar*) "logic"); | ||
| 156 | if (!xmlStrcmp(key, (const xmlChar*) "or")) | ||
| 157 | { | ||
| 158 | r.type = selrestr_t::type_t::orlogic; | ||
| 159 | } | ||
| 160 | xmlFree(key); | ||
| 161 | } | ||
| 162 | |||
| 163 | for (xmlNodePtr selrestr = top->xmlChildrenNode; selrestr != nullptr; selrestr = selrestr->next) | ||
| 164 | { | ||
| 165 | if (!xmlStrcmp(selrestr->name, (const xmlChar*) "SELRESTRS") || !xmlStrcmp(selrestr->name, (const xmlChar*) "SELRESTR")) | ||
| 166 | { | ||
| 167 | r.subordinates.push_back(parse_selrestrs(selrestr, filename)); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | } else if (!xmlStrcmp(top->name, (const xmlChar*) "SELRESTR")) | ||
| 172 | { | ||
| 173 | r.type = selrestr_t::type_t::singleton; | ||
| 174 | |||
| 175 | key = xmlGetProp(top, (xmlChar*) "Value"); | ||
| 176 | r.pos = (std::string((const char*)key) == "+"); | ||
| 177 | xmlFree(key); | ||
| 178 | |||
| 179 | key = xmlGetProp(top, (xmlChar*) "type"); | ||
| 180 | r.restriction = (const char*) key; | ||
| 181 | xmlFree(key); | ||
| 182 | } else { | ||
| 183 | // Invalid | ||
| 184 | std::cout << "Bad VerbNet file format: " << filename << std::endl; | ||
| 185 | print_usage(); | ||
| 186 | } | ||
| 187 | |||
| 188 | return r; | ||
| 189 | } | ||
| 190 | |||
| 191 | group_t& parse_group(xmlNodePtr top, std::string filename) | ||
| 71 | { | 192 | { |
| 72 | xmlChar* key = xmlGetProp(top, (xmlChar*) "ID"); | 193 | xmlChar* key = xmlGetProp(top, (xmlChar*) "ID"); |
| 73 | if (key == 0) | 194 | if (key == 0) |
| @@ -75,41 +196,183 @@ void parse_group(xmlNodePtr top, std::string filename) | |||
| 75 | std::cout << "Bad VerbNet file format: " << filename << std::endl; | 196 | std::cout << "Bad VerbNet file format: " << filename << std::endl; |
| 76 | print_usage(); | 197 | print_usage(); |
| 77 | } | 198 | } |
| 78 | std::string vnid = key; | 199 | std::string vnid = (const char*)key; |
| 79 | vnid = vnid.substr(vnid.find_first_of("-")+1); | 200 | vnid = vnid.substr(vnid.find_first_of("-")+1); |
| 80 | xmlFree(key); | 201 | xmlFree(key); |
| 81 | 202 | ||
| 82 | group g; | 203 | group_t g; |
| 83 | g.id = vnid; | 204 | g.id = vnid; |
| 84 | 205 | ||
| 85 | for (xmlNodePtr node = top->xmlChildrenNode; node != nullptr; node = node->next) | 206 | for (xmlNodePtr node = top->xmlChildrenNode; node != nullptr; node = node->next) |
| 86 | { | 207 | { |
| 87 | if (!xmlStrcmp(node->name, (const xmlChar*) "MEMBERS")) | 208 | if (!xmlStrcmp(node->name, (const xmlChar*) "SUBCLASSES")) |
| 209 | { | ||
| 210 | for (xmlNodePtr subclass = node->xmlChildrenNode; subclass != nullptr; subclass = subclass->next) | ||
| 211 | { | ||
| 212 | if (!xmlStrcmp(subclass->name, (const xmlChar*) "VNSUBCLASS")) | ||
| 213 | { | ||
| 214 | auto& sg = parse_group(subclass, filename); | ||
| 215 | sg.parent = vnid; | ||
| 216 | |||
| 217 | for (auto member : sg.members) | ||
| 218 | { | ||
| 219 | g.members.insert(member); | ||
| 220 | } | ||
| 221 | |||
| 222 | // The schema requires that subclasses appear after role definitions, so we can do this now | ||
| 223 | for (auto role : g.roles) | ||
| 224 | { | ||
| 225 | if (sg.roles.count(role.first) == 0) | ||
| 226 | { | ||
| 227 | sg.roles[role.first] = role.second; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | } | ||
| 231 | } | ||
| 232 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "MEMBERS")) | ||
| 88 | { | 233 | { |
| 89 | for (xmlNodePtr member = node->xmlChildrenNode; member != nullptr; member = member->next) | 234 | for (xmlNodePtr member = node->xmlChildrenNode; member != nullptr; member = member->next) |
| 90 | { | 235 | { |
| 91 | if (!xmlStrcmp(member->name, (const xmlChar*) "MEMBER")) | 236 | if (!xmlStrcmp(member->name, (const xmlChar*) "MEMBER")) |
| 92 | { | 237 | { |
| 93 | key = xmlGetProp(member, (xmlChar*) "name"); | 238 | key = xmlGetProp(member, (xmlChar*) "name"); |
| 94 | g.members.insert(key); | 239 | g.members.insert((const char*)key); |
| 95 | xmlFree(key); | 240 | xmlFree(key); |
| 96 | } | 241 | } |
| 97 | } | 242 | } |
| 243 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "THEMROLES")) | ||
| 244 | { | ||
| 245 | for (xmlNodePtr role = node->xmlChildrenNode; role != nullptr; role = role->next) | ||
| 246 | { | ||
| 247 | if (!xmlStrcmp(role->name, (const xmlChar*) "THEMROLE")) | ||
| 248 | { | ||
| 249 | selrestr_t r; | ||
| 250 | r.type = selrestr_t::type_t::empty; | ||
| 251 | |||
| 252 | key = xmlGetProp(role, (const xmlChar*) "type"); | ||
| 253 | std::string type = (const char*)key; | ||
| 254 | xmlFree(key); | ||
| 255 | |||
| 256 | for (xmlNodePtr rolenode = role->xmlChildrenNode; rolenode != nullptr; rolenode = rolenode->next) | ||
| 257 | { | ||
| 258 | if (!xmlStrcmp(rolenode->name, (const xmlChar*) "SELRESTRS")) | ||
| 259 | { | ||
| 260 | r = parse_selrestrs(rolenode, filename); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | g.roles[type] = r; | ||
| 265 | } | ||
| 266 | } | ||
| 98 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "FRAMES")) | 267 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "FRAMES")) |
| 99 | { | 268 | { |
| 100 | for (xmlNodePtr frame = node->xmlChildrenNode; frame != nullptr; frame = frame->next) | 269 | for (xmlNodePtr frame = node->xmlChildrenNode; frame != nullptr; frame = frame->next) |
| 101 | { | 270 | { |
| 102 | if (!xmlStrcmp(frame->name, (const xmlChar*) "FRAME")) | 271 | if (!xmlStrcmp(frame->name, (const xmlChar*) "FRAME")) |
| 103 | { | 272 | { |
| 273 | std::list<framepart_t> f; | ||
| 274 | |||
| 104 | for (xmlNodePtr framenode = frame->xmlChildrenNode; framenode != nullptr; framenode = framenode->next) | 275 | for (xmlNodePtr framenode = frame->xmlChildrenNode; framenode != nullptr; framenode = framenode->next) |
| 105 | { | 276 | { |
| 106 | 277 | if (!xmlStrcmp(framenode->name, (const xmlChar*) "SYNTAX")) | |
| 278 | { | ||
| 279 | for (xmlNodePtr syntaxnode = framenode->xmlChildrenNode; syntaxnode != nullptr; syntaxnode = syntaxnode->next) | ||
| 280 | { | ||
| 281 | framepart_t fp; | ||
| 282 | |||
| 283 | if (!xmlStrcmp(syntaxnode->name, (const xmlChar*) "NP")) | ||
| 284 | { | ||
| 285 | fp.type = framepart_t::type_t::np; | ||
| 286 | |||
| 287 | key = xmlGetProp(syntaxnode, (xmlChar*) "value"); | ||
| 288 | fp.role = (const char*)key; | ||
| 289 | xmlFree(key); | ||
| 290 | |||
| 291 | fp.selrestrs.type = selrestr_t::type_t::empty; | ||
| 292 | |||
| 293 | for (xmlNodePtr npnode = syntaxnode->xmlChildrenNode; npnode != nullptr; npnode = npnode->next) | ||
| 294 | { | ||
| 295 | if (!xmlStrcmp(npnode->name, (const xmlChar*) "SYNRESTRS")) | ||
| 296 | { | ||
| 297 | for (xmlNodePtr synrestr = npnode->xmlChildrenNode; synrestr != nullptr; synrestr = synrestr->next) | ||
| 298 | { | ||
| 299 | if (!xmlStrcmp(synrestr->name, (const xmlChar*) "SYNRESTR")) | ||
| 300 | { | ||
| 301 | key = xmlGetProp(synrestr, (xmlChar*) "type"); | ||
| 302 | fp.synrestrs.insert(std::string((const char*)key)); | ||
| 303 | xmlFree(key); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | if (!xmlStrcmp(npnode->name, (const xmlChar*) "SELRESTRS")) | ||
| 309 | { | ||
| 310 | fp.selrestrs = parse_selrestrs(npnode, filename); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | } else if (!xmlStrcmp(syntaxnode->name, (xmlChar*) "VERB")) | ||
| 314 | { | ||
| 315 | fp.type = framepart_t::type_t::v; | ||
| 316 | } else if (!xmlStrcmp(syntaxnode->name, (xmlChar*) "PREP")) | ||
| 317 | { | ||
| 318 | fp.type = framepart_t::type_t::pp; | ||
| 319 | |||
| 320 | if (xmlHasProp(syntaxnode, (xmlChar*) "value")) | ||
| 321 | { | ||
| 322 | key = xmlGetProp(syntaxnode, (xmlChar*) "value"); | ||
| 323 | std::string choices = (const char*)key; | ||
| 324 | xmlFree(key); | ||
| 325 | |||
| 326 | fp.choices = verbly::split<std::list<std::string>>(choices, " "); | ||
| 327 | } | ||
| 328 | |||
| 329 | for (xmlNodePtr npnode = syntaxnode->xmlChildrenNode; npnode != nullptr; npnode = npnode->next) | ||
| 330 | { | ||
| 331 | if (!xmlStrcmp(npnode->name, (const xmlChar*) "SELRESTRS")) | ||
| 332 | { | ||
| 333 | for (xmlNodePtr synrestr = npnode->xmlChildrenNode; synrestr != nullptr; synrestr = synrestr->next) | ||
| 334 | { | ||
| 335 | if (!xmlStrcmp(synrestr->name, (const xmlChar*) "SELRESTR")) | ||
| 336 | { | ||
| 337 | key = xmlGetProp(synrestr, (xmlChar*) "type"); | ||
| 338 | fp.preprestrs.insert(std::string((const char*)key)); | ||
| 339 | xmlFree(key); | ||
| 340 | } | ||
| 341 | } | ||
| 342 | } | ||
| 343 | } | ||
| 344 | } else if (!xmlStrcmp(syntaxnode->name, (xmlChar*) "ADJ")) | ||
| 345 | { | ||
| 346 | fp.type = framepart_t::type_t::adj; | ||
| 347 | } else if (!xmlStrcmp(syntaxnode->name, (xmlChar*) "ADV")) | ||
| 348 | { | ||
| 349 | fp.type = framepart_t::type_t::adv; | ||
| 350 | } else if (!xmlStrcmp(syntaxnode->name, (xmlChar*) "LEX")) | ||
| 351 | { | ||
| 352 | fp.type = framepart_t::type_t::lex; | ||
| 353 | |||
| 354 | key = xmlGetProp(syntaxnode, (xmlChar*) "value"); | ||
| 355 | fp.lexval = (const char*)key; | ||
| 356 | xmlFree(key); | ||
| 357 | } else { | ||
| 358 | continue; | ||
| 359 | } | ||
| 360 | |||
| 361 | f.push_back(fp); | ||
| 362 | } | ||
| 363 | |||
| 364 | g.frames.push_back(f); | ||
| 365 | } | ||
| 107 | } | 366 | } |
| 108 | } | 367 | } |
| 109 | } | 368 | } |
| 110 | } | 369 | } |
| 111 | } | 370 | } |
| 112 | }*/ | 371 | |
| 372 | groups[vnid] = g; | ||
| 373 | |||
| 374 | return groups[vnid]; | ||
| 375 | } | ||
| 113 | 376 | ||
| 114 | int main(int argc, char** argv) | 377 | int main(int argc, char** argv) |
| 115 | { | 378 | { |
| @@ -118,7 +381,10 @@ int main(int argc, char** argv) | |||
| 118 | print_usage(); | 381 | print_usage(); |
| 119 | } | 382 | } |
| 120 | 383 | ||
| 121 | /*DIR* dir; | 384 | // VerbNet data |
| 385 | std::cout << "Reading verb frames..." << std::endl; | ||
| 386 | |||
| 387 | DIR* dir; | ||
| 122 | if ((dir = opendir(argv[1])) == nullptr) | 388 | if ((dir = opendir(argv[1])) == nullptr) |
| 123 | { | 389 | { |
| 124 | std::cout << "Invalid VerbNet data directory." << std::endl; | 390 | std::cout << "Invalid VerbNet data directory." << std::endl; |
| @@ -160,7 +426,7 @@ int main(int argc, char** argv) | |||
| 160 | parse_group(top, filename); | 426 | parse_group(top, filename); |
| 161 | } | 427 | } |
| 162 | 428 | ||
| 163 | closedir(dir);*/ | 429 | closedir(dir); |
| 164 | 430 | ||
| 165 | // Get verbs from AGID | 431 | // Get verbs from AGID |
| 166 | std::cout << "Reading inflections..." << std::endl; | 432 | std::cout << "Reading inflections..." << std::endl; |
| @@ -222,7 +488,7 @@ int main(int argc, char** argv) | |||
| 222 | { | 488 | { |
| 223 | case 'V': | 489 | case 'V': |
| 224 | { | 490 | { |
| 225 | verb v; | 491 | verb_t v; |
| 226 | v.infinitive = word; | 492 | v.infinitive = word; |
| 227 | if (forms.size() == 4) | 493 | if (forms.size() == 4) |
| 228 | { | 494 | { |
| @@ -258,7 +524,7 @@ int main(int argc, char** argv) | |||
| 258 | 524 | ||
| 259 | case 'A': | 525 | case 'A': |
| 260 | { | 526 | { |
| 261 | adjective adj; | 527 | adjective_t adj; |
| 262 | adj.base = word; | 528 | adj.base = word; |
| 263 | if (forms.size() == 2) | 529 | if (forms.size() == 2) |
| 264 | { | 530 | { |
| @@ -276,7 +542,7 @@ int main(int argc, char** argv) | |||
| 276 | 542 | ||
| 277 | case 'N': | 543 | case 'N': |
| 278 | { | 544 | { |
| 279 | noun n; | 545 | noun_t n; |
| 280 | n.singular = word; | 546 | n.singular = word; |
| 281 | if (forms.size() == 1) | 547 | if (forms.size() == 1) |
| 282 | { | 548 | { |
| @@ -388,6 +654,85 @@ int main(int argc, char** argv) | |||
| 388 | sqlite3_finalize(schmstmt); | 654 | sqlite3_finalize(schmstmt); |
| 389 | } | 655 | } |
| 390 | 656 | ||
| 657 | std::cout << "Writing prepositions..." << std::endl; | ||
| 658 | std::ifstream prepfile("prepositions.txt"); | ||
| 659 | if (!prepfile.is_open()) | ||
| 660 | { | ||
| 661 | std::cout << "Could not find prepositions file" << std::endl; | ||
| 662 | print_usage(); | ||
| 663 | } | ||
| 664 | |||
| 665 | for (;;) | ||
| 666 | { | ||
| 667 | std::string line; | ||
| 668 | if (!getline(prepfile, line)) | ||
| 669 | { | ||
| 670 | break; | ||
| 671 | } | ||
| 672 | |||
| 673 | if (line.back() == '\r') | ||
| 674 | { | ||
| 675 | line.pop_back(); | ||
| 676 | } | ||
| 677 | |||
| 678 | std::regex relation("^([^:]+): (.+)"); | ||
| 679 | std::smatch relation_data; | ||
| 680 | std::regex_search(line, relation_data, relation); | ||
| 681 | std::string prep = relation_data[1]; | ||
| 682 | std::list<std::string> groups = verbly::split<std::list<std::string>>(relation_data[2], ", "); | ||
| 683 | |||
| 684 | std::string query("INSERT INTO prepositions (form) VALUES (?)"); | ||
| 685 | sqlite3_stmt* ppstmt; | ||
| 686 | |||
| 687 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 688 | { | ||
| 689 | db_error(ppdb, query); | ||
| 690 | } | ||
| 691 | |||
| 692 | sqlite3_bind_text(ppstmt, 1, prep.c_str(), prep.length(), SQLITE_STATIC); | ||
| 693 | |||
| 694 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
| 695 | { | ||
| 696 | db_error(ppdb, query); | ||
| 697 | } | ||
| 698 | |||
| 699 | sqlite3_finalize(ppstmt); | ||
| 700 | |||
| 701 | query = "SELECT last_insert_rowid()"; | ||
| 702 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 703 | { | ||
| 704 | db_error(ppdb, query); | ||
| 705 | } | ||
| 706 | |||
| 707 | if (sqlite3_step(ppstmt) != SQLITE_ROW) | ||
| 708 | { | ||
| 709 | db_error(ppdb, query); | ||
| 710 | } | ||
| 711 | |||
| 712 | int rowid = sqlite3_column_int(ppstmt, 0); | ||
| 713 | sqlite3_finalize(ppstmt); | ||
| 714 | |||
| 715 | for (auto group : groups) | ||
| 716 | { | ||
| 717 | query = "INSERT INTO preposition_groups (preposition_id, groupname) VALUES (?, ?)"; | ||
| 718 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 719 | { | ||
| 720 | db_error(ppdb, query); | ||
| 721 | } | ||
| 722 | |||
| 723 | sqlite3_bind_int(ppstmt, 1, rowid); | ||
| 724 | sqlite3_bind_text(ppstmt, 2, group.c_str(), group.length(), SQLITE_STATIC); | ||
| 725 | |||
| 726 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
| 727 | { | ||
| 728 | db_error(ppdb, query); | ||
| 729 | } | ||
| 730 | |||
| 731 | sqlite3_finalize(ppstmt); | ||
| 732 | } | ||
| 733 | } | ||
| 734 | |||
| 735 | |||
| 391 | { | 736 | { |
| 392 | progress ppgs("Writing verbs...", verbs.size()); | 737 | progress ppgs("Writing verbs...", verbs.size()); |
| 393 | for (auto& mapping : verbs) | 738 | for (auto& mapping : verbs) |
| @@ -431,6 +776,8 @@ int main(int argc, char** argv) | |||
| 431 | 776 | ||
| 432 | sqlite3_finalize(ppstmt); | 777 | sqlite3_finalize(ppstmt); |
| 433 | 778 | ||
| 779 | mapping.second.id = rowid; | ||
| 780 | |||
| 434 | for (auto pronunciation : pronunciations[canonical]) | 781 | for (auto pronunciation : pronunciations[canonical]) |
| 435 | { | 782 | { |
| 436 | query = "INSERT INTO verb_pronunciations (verb_id, pronunciation) VALUES (?, ?)"; | 783 | query = "INSERT INTO verb_pronunciations (verb_id, pronunciation) VALUES (?, ?)"; |
| @@ -455,6 +802,160 @@ int main(int argc, char** argv) | |||
| 455 | } | 802 | } |
| 456 | } | 803 | } |
| 457 | 804 | ||
| 805 | { | ||
| 806 | progress ppgs("Writing verb frames...", groups.size()); | ||
| 807 | for (auto& mapping : groups) | ||
| 808 | { | ||
| 809 | std::list<json> roledatal; | ||
| 810 | std::transform(std::begin(mapping.second.roles), std::end(mapping.second.roles), std::back_inserter(roledatal), [] (std::pair<std::string, selrestr_t> r) { | ||
| 811 | json role; | ||
| 812 | role["type"] = r.first; | ||
| 813 | role["selrestrs"] = export_selrestrs(r.second); | ||
| 814 | |||
| 815 | return role; | ||
| 816 | }); | ||
| 817 | |||
| 818 | json roledata(roledatal); | ||
| 819 | std::string rdm = roledata.dump(); | ||
| 820 | |||
| 821 | sqlite3_stmt* ppstmt; | ||
| 822 | std::string query("INSERT INTO groups (data) VALUES (?)"); | ||
| 823 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 824 | { | ||
| 825 | db_error(ppdb, query); | ||
| 826 | } | ||
| 827 | |||
| 828 | sqlite3_bind_blob(ppstmt, 1, rdm.c_str(), rdm.size(), SQLITE_STATIC); | ||
| 829 | |||
| 830 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
| 831 | { | ||
| 832 | db_error(ppdb, query); | ||
| 833 | } | ||
| 834 | |||
| 835 | sqlite3_finalize(ppstmt); | ||
| 836 | |||
| 837 | query = "SELECT last_insert_rowid()"; | ||
| 838 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 839 | { | ||
| 840 | db_error(ppdb, query); | ||
| 841 | } | ||
| 842 | |||
| 843 | if (sqlite3_step(ppstmt) != SQLITE_ROW) | ||
| 844 | { | ||
| 845 | db_error(ppdb, query); | ||
| 846 | } | ||
| 847 | |||
| 848 | int gid = sqlite3_column_int(ppstmt, 0); | ||
| 849 | sqlite3_finalize(ppstmt); | ||
| 850 | |||
| 851 | for (auto frame : mapping.second.frames) | ||
| 852 | { | ||
| 853 | std::list<json> fdatap; | ||
| 854 | std::transform(std::begin(frame), std::end(frame), std::back_inserter(fdatap), [] (framepart_t& fp) { | ||
| 855 | json part; | ||
| 856 | |||
| 857 | switch (fp.type) | ||
| 858 | { | ||
| 859 | case framepart_t::type_t::np: | ||
| 860 | { | ||
| 861 | part["type"] = "np"; | ||
| 862 | part["role"] = fp.role; | ||
| 863 | part["selrestrs"] = export_selrestrs(fp.selrestrs); | ||
| 864 | part["synrestrs"] = fp.synrestrs; | ||
| 865 | |||
| 866 | break; | ||
| 867 | } | ||
| 868 | |||
| 869 | case framepart_t::type_t::pp: | ||
| 870 | { | ||
| 871 | part["type"] = "pp"; | ||
| 872 | part["values"] = fp.choices; | ||
| 873 | part["preprestrs"] = fp.preprestrs; | ||
| 874 | |||
| 875 | break; | ||
| 876 | } | ||
| 877 | |||
| 878 | case framepart_t::type_t::v: | ||
| 879 | { | ||
| 880 | part["type"] = "v"; | ||
| 881 | |||
| 882 | break; | ||
| 883 | } | ||
| 884 | |||
| 885 | case framepart_t::type_t::adj: | ||
| 886 | { | ||
| 887 | part["type"] = "adj"; | ||
| 888 | |||
| 889 | break; | ||
| 890 | } | ||
| 891 | |||
| 892 | case framepart_t::type_t::adv: | ||
| 893 | { | ||
| 894 | part["type"] = "adv"; | ||
| 895 | |||
| 896 | break; | ||
| 897 | } | ||
| 898 | |||
| 899 | case framepart_t::type_t::lex: | ||
| 900 | { | ||
| 901 | part["type"] = "lex"; | ||
| 902 | part["value"] = fp.lexval; | ||
| 903 | |||
| 904 | break; | ||
| 905 | } | ||
| 906 | } | ||
| 907 | |||
| 908 | return part; | ||
| 909 | }); | ||
| 910 | |||
| 911 | json fdata(fdatap); | ||
| 912 | std::string marshall = fdata.dump(); | ||
| 913 | |||
| 914 | query = "INSERT INTO frames (group_id, data) VALUES (?, ?)"; | ||
| 915 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 916 | { | ||
| 917 | db_error(ppdb, query); | ||
| 918 | } | ||
| 919 | |||
| 920 | sqlite3_bind_int(ppstmt, 1, gid); | ||
| 921 | sqlite3_bind_blob(ppstmt, 2, marshall.c_str(), marshall.length(), SQLITE_STATIC); | ||
| 922 | |||
| 923 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
| 924 | { | ||
| 925 | db_error(ppdb, query); | ||
| 926 | } | ||
| 927 | |||
| 928 | sqlite3_finalize(ppstmt); | ||
| 929 | } | ||
| 930 | |||
| 931 | for (auto member : mapping.second.members) | ||
| 932 | { | ||
| 933 | if (verbs.count(member) == 1) | ||
| 934 | { | ||
| 935 | auto& v = verbs[member]; | ||
| 936 | |||
| 937 | query = "INSERT INTO verb_groups (verb_id, group_id) VALUES (?, ?)"; | ||
| 938 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 939 | { | ||
| 940 | db_error(ppdb, query); | ||
| 941 | } | ||
| 942 | |||
| 943 | sqlite3_bind_int(ppstmt, 1, v.id); | ||
| 944 | sqlite3_bind_int(ppstmt, 2, gid); | ||
| 945 | |||
| 946 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
| 947 | { | ||
| 948 | db_error(ppdb, query); | ||
| 949 | } | ||
| 950 | |||
| 951 | sqlite3_finalize(ppstmt); | ||
| 952 | } | ||
| 953 | } | ||
| 954 | |||
| 955 | ppgs.update(); | ||
| 956 | } | ||
| 957 | } | ||
| 958 | |||
| 458 | // Get nouns/adjectives/adverbs from WordNet | 959 | // Get nouns/adjectives/adverbs from WordNet |
| 459 | // Useful relations: | 960 | // Useful relations: |
| 460 | // - s: master list | 961 | // - s: master list |
| diff --git a/generator/prepositions.txt b/generator/prepositions.txt new file mode 100644 index 0000000..283e5c4 --- /dev/null +++ b/generator/prepositions.txt | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | from: src, path, spatial, loc | ||
| 2 | out: src, path, spatial | ||
| 3 | out of: src, path, spatial, loc | ||
| 4 | off: src, path, spatial, loc | ||
| 5 | off of: src, path, spatial | ||
| 6 | into: dest_conf, dest, path, spatial | ||
| 7 | onto: dest_conf, dest, path, spatial | ||
| 8 | for: dest_dir, dest, path, spatial | ||
| 9 | at: dest_dir, dest, path, spatial, loc | ||
| 10 | to: dest_dir, dest, path, spatial | ||
| 11 | towards: dest_dir, dest, path, spatial | ||
| 12 | along: dir, path, spatial, loc | ||
| 13 | across: dir, path, spatial | ||
| 14 | around: dir, path, spatial, loc | ||
| 15 | down: dir, path, spatial | ||
| 16 | over: dir, path, spatial, loc | ||
| 17 | past: dir, path, spatial | ||
| 18 | round: dir, path, spatial, loc | ||
| 19 | through: dir, path, spatial | ||
| 20 | towards: dir, path, spatial | ||
| 21 | up: dir, path, spatial | ||
| 22 | about: loc, spatial | ||
| 23 | above: loc, spatial | ||
| 24 | against: loc, spatial | ||
| 25 | alongside: loc, spatial | ||
| 26 | amid: loc, spatial | ||
| 27 | among: loc, spatial | ||
| 28 | amongst: loc, spatial | ||
| 29 | astride: loc, spatial | ||
| 30 | athwart: loc, spatial | ||
| 31 | before: loc, spatial | ||
| 32 | behind: loc, spatial | ||
| 33 | beside: loc, spatial | ||
| 34 | between: loc, spatial | ||
| 35 | beyond: loc, spatial | ||
| 36 | by: loc, spatial | ||
| 37 | in: loc, spatial | ||
| 38 | in front of: loc, spatial | ||
| 39 | inside: loc, spatial | ||
| 40 | near: loc, spatial | ||
| 41 | next to: loc, spatial | ||
| 42 | on: loc, spatial | ||
| 43 | opposite: loc, spatial | ||
| 44 | outside: loc, spatial | ||
| 45 | throughout: loc, spatial | ||
| 46 | under: loc, spatial | ||
| 47 | underneath: loc, spatial | ||
| 48 | upon: loc, spatial | ||
| 49 | within: loc, spatial \ No newline at end of file | ||
| diff --git a/generator/schema.sql b/generator/schema.sql index 8e1e822..2295444 100644 --- a/generator/schema.sql +++ b/generator/schema.sql | |||
| @@ -11,8 +11,7 @@ CREATE TABLE `verbs` ( | |||
| 11 | DROP TABLE IF EXISTS `groups`; | 11 | DROP TABLE IF EXISTS `groups`; |
| 12 | CREATE TABLE `groups` ( | 12 | CREATE TABLE `groups` ( |
| 13 | `group_id` INTEGER PRIMARY KEY, | 13 | `group_id` INTEGER PRIMARY KEY, |
| 14 | `parent_id` INTEGER, | 14 | `data` BLOB NOT NULL |
| 15 | FOREIGN KEY (`parent_id`) REFERENCES `groups`(`group_id`) | ||
| 16 | ); | 15 | ); |
| 17 | 16 | ||
| 18 | DROP TABLE IF EXISTS `frames`; | 17 | DROP TABLE IF EXISTS `frames`; |
| @@ -251,3 +250,16 @@ CREATE TABLE `adverb_adverb_derivation` ( | |||
| 251 | FOREIGN KEY (`adverb_1_id`) REFERENCES `adverbs`(`adverb_id`), | 250 | FOREIGN KEY (`adverb_1_id`) REFERENCES `adverbs`(`adverb_id`), |
| 252 | FOREIGN KEY (`adverb_2_id`) REFERENCES `adverbs`(`adverb_id`) | 251 | FOREIGN KEY (`adverb_2_id`) REFERENCES `adverbs`(`adverb_id`) |
| 253 | ); | 252 | ); |
| 253 | |||
| 254 | DROP TABLE IF EXISTS `prepositions`; | ||
| 255 | CREATE TABLE `prepositions` ( | ||
| 256 | `preposition_id` INTEGER PRIMARY KEY, | ||
| 257 | `form` VARCHAR(32) NOT NULL | ||
| 258 | ); | ||
| 259 | |||
| 260 | DROP TABLE IF EXISTS `preposition_groups`; | ||
| 261 | CREATE TABLE `preposition_groups` ( | ||
| 262 | `preposition_id` INTEGER NOT NULL, | ||
| 263 | `groupname` VARCHAR(32) NOT NULL, | ||
| 264 | FOREIGN KEY (`preposition_id`) REFERENCES `prepositions`(`preposition_id`) | ||
| 265 | ); | ||
| diff --git a/generator/vn.diff b/generator/vn.diff new file mode 100644 index 0000000..f636d28 --- /dev/null +++ b/generator/vn.diff | |||
| @@ -0,0 +1,482 @@ | |||
| 1 | diff /Users/hatkirby/Downloads/new_vn 2/admit-65.xml datadir/vn/admit-65.xml | ||
| 2 | 104c104 | ||
| 3 | < <SELRESTRS logic="or"> | ||
| 4 | --- | ||
| 5 | > <SELRESTRS> | ||
| 6 | diff /Users/hatkirby/Downloads/new_vn 2/amuse-31.1.xml datadir/vn/amuse-31.1.xml | ||
| 7 | 270a271,273 | ||
| 8 | > <THEMROLE type="Cause"> | ||
| 9 | > <SELRESTRS/> | ||
| 10 | > </THEMROLE> | ||
| 11 | 368c371,373 | ||
| 12 | < <LEX value="'s"/> | ||
| 13 | --- | ||
| 14 | > <NP value="Cause"> | ||
| 15 | > <SYNRESTRS/> | ||
| 16 | > </NP> | ||
| 17 | 404c409,411 | ||
| 18 | < <SYNRESTRS/> | ||
| 19 | --- | ||
| 20 | > <SYNRESTRS> | ||
| 21 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 22 | > </SYNRESTRS> | ||
| 23 | diff /Users/hatkirby/Downloads/new_vn 2/animal_sounds-38.xml datadir/vn/animal_sounds-38.xml | ||
| 24 | 186a187,191 | ||
| 25 | > <PREP> | ||
| 26 | > <SELRESTRS> | ||
| 27 | > <SELRESTR Value="+" type="loc" /> | ||
| 28 | > </SELRESTRS> | ||
| 29 | > </PREP> | ||
| 30 | diff /Users/hatkirby/Downloads/new_vn 2/assessment-34.1.xml datadir/vn/assessment-34.1.xml | ||
| 31 | 103d102 | ||
| 32 | < <LEX value="'s"/> | ||
| 33 | diff /Users/hatkirby/Downloads/new_vn 2/battle-36.4.xml datadir/vn/battle-36.4.xml | ||
| 34 | 96c96 | ||
| 35 | < <SYNRESTR Value="+" type="what_extract"/> | ||
| 36 | --- | ||
| 37 | > <SYNRESTR Value="+" type="wh_comp"/> | ||
| 38 | diff /Users/hatkirby/Downloads/new_vn 2/become-109.1.xml datadir/vn/become-109.1.xml | ||
| 39 | 34c34,36 | ||
| 40 | < <SYNRESTRS/> | ||
| 41 | --- | ||
| 42 | > <SYNRESTRS> | ||
| 43 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 44 | > </SYNRESTRS> | ||
| 45 | diff /Users/hatkirby/Downloads/new_vn 2/beg-58.2.xml datadir/vn/beg-58.2.xml | ||
| 46 | 41c41 | ||
| 47 | < <SYNRESTR Value="-" type="for_comp"/> | ||
| 48 | --- | ||
| 49 | > <SYNRESTR Value="+" type="for_comp"/> | ||
| 50 | diff /Users/hatkirby/Downloads/new_vn 2/bend-45.2.xml datadir/vn/bend-45.2.xml | ||
| 51 | 47c47,49 | ||
| 52 | < <SELRESTRS/> | ||
| 53 | --- | ||
| 54 | > <SELRESTRS> | ||
| 55 | > <SELRESTR Value="+" type="state"/> | ||
| 56 | > </SELRESTRS> | ||
| 57 | 230c232,234 | ||
| 58 | < <SYNRESTRS/> | ||
| 59 | --- | ||
| 60 | > <SYNRESTRS> | ||
| 61 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 62 | > </SYNRESTRS> | ||
| 63 | 280,282c284 | ||
| 64 | < <SELRESTRS> | ||
| 65 | < <SELRESTR Value="+" type="state"/> | ||
| 66 | < </SELRESTRS> | ||
| 67 | --- | ||
| 68 | > <SELRESTRS/> | ||
| 69 | 332,334c334 | ||
| 70 | < <SELRESTRS> | ||
| 71 | < <SELRESTR Value="+" type="state"/> | ||
| 72 | < </SELRESTRS> | ||
| 73 | --- | ||
| 74 | > <SELRESTRS/> | ||
| 75 | diff /Users/hatkirby/Downloads/new_vn 2/break-45.1.xml datadir/vn/break-45.1.xml | ||
| 76 | 255c255,257 | ||
| 77 | < <SYNRESTRS/> | ||
| 78 | --- | ||
| 79 | > <SYNRESTRS> | ||
| 80 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 81 | > </SYNRESTRS> | ||
| 82 | 307c309,311 | ||
| 83 | < <SYNRESTRS/> | ||
| 84 | --- | ||
| 85 | > <SYNRESTRS> | ||
| 86 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 87 | > </SYNRESTRS> | ||
| 88 | diff /Users/hatkirby/Downloads/new_vn 2/characterize-29.2.xml datadir/vn/characterize-29.2.xml | ||
| 89 | 107c107 | ||
| 90 | < <LEX value="as"/> | ||
| 91 | --- | ||
| 92 | > <LEX value="to be"/> | ||
| 93 | 109,111c109,111 | ||
| 94 | < <SYNRESTRS> | ||
| 95 | < <SYNRESTR Value="+" type="small_clause"/> | ||
| 96 | < </SYNRESTRS> | ||
| 97 | --- | ||
| 98 | > <SYNRESTRS> | ||
| 99 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 100 | > </SYNRESTRS> | ||
| 101 | 386a387,391 | ||
| 102 | > <NP value="Attribute"> | ||
| 103 | > <SYNRESTRS> | ||
| 104 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 105 | > </SYNRESTRS> | ||
| 106 | > </NP> | ||
| 107 | diff /Users/hatkirby/Downloads/new_vn 2/coloring-24.xml datadir/vn/coloring-24.xml | ||
| 108 | 89c89,91 | ||
| 109 | < <SYNRESTRS/> | ||
| 110 | --- | ||
| 111 | > <SYNRESTRS> | ||
| 112 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 113 | > </SYNRESTRS> | ||
| 114 | diff /Users/hatkirby/Downloads/new_vn 2/confess-37.10.xml datadir/vn/confess-37.10.xml | ||
| 115 | 110a111,115 | ||
| 116 | > <NP value="Attribute"> | ||
| 117 | > <SYNRESTRS> | ||
| 118 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 119 | > </SYNRESTRS> | ||
| 120 | > </NP> | ||
| 121 | diff /Users/hatkirby/Downloads/new_vn 2/consider-29.9.xml datadir/vn/consider-29.9.xml | ||
| 122 | 191,193c191,193 | ||
| 123 | < <SYNRESTRS> | ||
| 124 | < <SYNRESTR Value="-" type="sentential"/> | ||
| 125 | < </SYNRESTRS> | ||
| 126 | --- | ||
| 127 | > <SYNRESTRS> | ||
| 128 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 129 | > </SYNRESTRS> | ||
| 130 | 334,336c334,336 | ||
| 131 | < <SYNRESTRS> | ||
| 132 | < <SYNRESTR Value="-" type="sentential"/> | ||
| 133 | < </SYNRESTRS> | ||
| 134 | --- | ||
| 135 | > <SYNRESTRS> | ||
| 136 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 137 | > </SYNRESTRS> | ||
| 138 | 468,470c468,470 | ||
| 139 | < <SYNRESTRS> | ||
| 140 | < <SYNRESTR Value="-" type="sentential"/> | ||
| 141 | < </SYNRESTRS> | ||
| 142 | --- | ||
| 143 | > <SYNRESTRS> | ||
| 144 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 145 | > </SYNRESTRS> | ||
| 146 | 554,556c554,556 | ||
| 147 | < <SYNRESTRS> | ||
| 148 | < <SYNRESTR Value="-" type="sentential"/> | ||
| 149 | < </SYNRESTRS> | ||
| 150 | --- | ||
| 151 | > <SYNRESTRS> | ||
| 152 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 153 | > </SYNRESTRS> | ||
| 154 | diff /Users/hatkirby/Downloads/new_vn 2/cut-21.1.xml datadir/vn/cut-21.1.xml | ||
| 155 | 316c316,318 | ||
| 156 | < <SYNRESTRS/> | ||
| 157 | --- | ||
| 158 | > <SYNRESTRS> | ||
| 159 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 160 | > </SYNRESTRS> | ||
| 161 | 368c370,372 | ||
| 162 | < <SYNRESTRS/> | ||
| 163 | --- | ||
| 164 | > <SYNRESTRS> | ||
| 165 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 166 | > </SYNRESTRS> | ||
| 167 | 560c564,566 | ||
| 168 | < <SYNRESTRS/> | ||
| 169 | --- | ||
| 170 | > <SYNRESTRS> | ||
| 171 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 172 | > </SYNRESTRS> | ||
| 173 | diff /Users/hatkirby/Downloads/new_vn 2/declare-29.4.xml datadir/vn/declare-29.4.xml | ||
| 174 | 33,35c33,35 | ||
| 175 | < <SYNRESTRS> | ||
| 176 | < <SYNRESTR Value="-" type="sentential"/> | ||
| 177 | < </SYNRESTRS> | ||
| 178 | --- | ||
| 179 | > <SYNRESTRS> | ||
| 180 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 181 | > </SYNRESTRS> | ||
| 182 | 122,124c122,124 | ||
| 183 | < <SYNRESTRS> | ||
| 184 | < <SYNRESTR Value="-" type="sentential"/> | ||
| 185 | < </SYNRESTRS> | ||
| 186 | --- | ||
| 187 | > <SYNRESTRS> | ||
| 188 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 189 | > </SYNRESTRS> | ||
| 190 | 244,246c244,246 | ||
| 191 | < <SYNRESTRS> | ||
| 192 | < <SYNRESTR Value="-" type="sentential"/> | ||
| 193 | < </SYNRESTRS> | ||
| 194 | --- | ||
| 195 | > <SYNRESTRS> | ||
| 196 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 197 | > </SYNRESTRS> | ||
| 198 | diff /Users/hatkirby/Downloads/new_vn 2/estimate-34.2.xml datadir/vn/estimate-34.2.xml | ||
| 199 | 123a124 | ||
| 200 | > <LEX value="to be"/> | ||
| 201 | 125,127c126,128 | ||
| 202 | < <SYNRESTRS> | ||
| 203 | < <SYNRESTR Value="+" type="to_be"/> | ||
| 204 | < </SYNRESTRS> | ||
| 205 | --- | ||
| 206 | > <SYNRESTRS> | ||
| 207 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 208 | > </SYNRESTRS> | ||
| 209 | diff /Users/hatkirby/Downloads/new_vn 2/get-13.5.1.xml datadir/vn/get-13.5.1.xml | ||
| 210 | 55,56c55 | ||
| 211 | < <SELRESTR Value="-" type="location"/> | ||
| 212 | < <SELRESTR Value="-" type="region"/> | ||
| 213 | --- | ||
| 214 | > <SELRESTR Value="+" type="currency"/> | ||
| 215 | diff /Users/hatkirby/Downloads/new_vn 2/hit-18.1.xml datadir/vn/hit-18.1.xml | ||
| 216 | 234c234,236 | ||
| 217 | < <SYNRESTRS/> | ||
| 218 | --- | ||
| 219 | > <SYNRESTRS> | ||
| 220 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 221 | > </SYNRESTRS> | ||
| 222 | 294c296,298 | ||
| 223 | < <SYNRESTRS/> | ||
| 224 | --- | ||
| 225 | > <SYNRESTRS> | ||
| 226 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 227 | > </SYNRESTRS> | ||
| 228 | 619c623,625 | ||
| 229 | < <SYNRESTRS/> | ||
| 230 | --- | ||
| 231 | > <SYNRESTRS> | ||
| 232 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 233 | > </SYNRESTRS> | ||
| 234 | diff /Users/hatkirby/Downloads/new_vn 2/instr_communication-37.4.xml datadir/vn/instr_communication-37.4.xml | ||
| 235 | 195c195,197 | ||
| 236 | < <SYNRESTRS/> | ||
| 237 | --- | ||
| 238 | > <SYNRESTRS> | ||
| 239 | > <SYNRESTR Value="+" type="quotation"/> | ||
| 240 | > </SYNRESTRS> | ||
| 241 | 233c235,237 | ||
| 242 | < <SYNRESTRS/> | ||
| 243 | --- | ||
| 244 | > <SYNRESTRS> | ||
| 245 | > <SYNRESTR Value="+" type="quotation"/> | ||
| 246 | > </SYNRESTRS> | ||
| 247 | diff /Users/hatkirby/Downloads/new_vn 2/judgment-33.xml datadir/vn/judgment-33.xml | ||
| 248 | 187a188,190 | ||
| 249 | > <NP value="Attribute"> | ||
| 250 | > <SYNRESTRS/> | ||
| 251 | > </NP> | ||
| 252 | 243a247 | ||
| 253 | > <LEX value="to be"/> | ||
| 254 | 245,247c249 | ||
| 255 | < <SYNRESTRS> | ||
| 256 | < <SYNRESTR Value="+" type="small_clause"/> | ||
| 257 | < </SYNRESTRS> | ||
| 258 | --- | ||
| 259 | > <SYNRESTRS/> | ||
| 260 | diff /Users/hatkirby/Downloads/new_vn 2/manner_speaking-37.3.xml datadir/vn/manner_speaking-37.3.xml | ||
| 261 | 264c264,266 | ||
| 262 | < <SYNRESTRS/> | ||
| 263 | --- | ||
| 264 | > <SYNRESTRS> | ||
| 265 | > <SYNRESTR Value="+" type="quotation"/> | ||
| 266 | > </SYNRESTRS> | ||
| 267 | 603c605,607 | ||
| 268 | < <SYNRESTRS/> | ||
| 269 | --- | ||
| 270 | > <SYNRESTRS> | ||
| 271 | > <SYNRESTR Value="+" type="quotation"/> | ||
| 272 | > </SYNRESTRS> | ||
| 273 | diff /Users/hatkirby/Downloads/new_vn 2/other_cos-45.4.xml datadir/vn/other_cos-45.4.xml | ||
| 274 | 534c534,536 | ||
| 275 | < <SYNRESTRS/> | ||
| 276 | --- | ||
| 277 | > <SYNRESTRS> | ||
| 278 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 279 | > </SYNRESTRS> | ||
| 280 | diff /Users/hatkirby/Downloads/new_vn 2/pocket-9.10.xml datadir/vn/pocket-9.10.xml | ||
| 281 | 256c256,258 | ||
| 282 | < <SYNRESTRS/> | ||
| 283 | --- | ||
| 284 | > <SYNRESTRS> | ||
| 285 | > <SYNRESTR Value="+" type="adv-loc"/> | ||
| 286 | > </SYNRESTRS> | ||
| 287 | diff /Users/hatkirby/Downloads/new_vn 2/poison-42.2.xml datadir/vn/poison-42.2.xml | ||
| 288 | 93c93,95 | ||
| 289 | < <SYNRESTRS/> | ||
| 290 | --- | ||
| 291 | > <SYNRESTRS> | ||
| 292 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 293 | > </SYNRESTRS> | ||
| 294 | diff /Users/hatkirby/Downloads/new_vn 2/pour-9.5.xml datadir/vn/pour-9.5.xml | ||
| 295 | 59,61c59,62 | ||
| 296 | < <SELRESTRS> | ||
| 297 | < <SELRESTR Value="+" type="path"/> | ||
| 298 | < <SELRESTR Value="-" type="dest_dir"/> | ||
| 299 | --- | ||
| 300 | > <SELRESTRS logic="or"> | ||
| 301 | > <SELRESTR Value="+" type="dir"/> | ||
| 302 | > <SELRESTR Value="+" type="src"/> | ||
| 303 | > <SELRESTR Value="+" type="dest_conf"/> | ||
| 304 | 157,160c158,162 | ||
| 305 | < <SELRESTRS> | ||
| 306 | < <SELRESTR Value="+" type="path"/> | ||
| 307 | < <SELRESTR Value="-" type="dest_dir"/> | ||
| 308 | < </SELRESTRS> | ||
| 309 | --- | ||
| 310 | > <SELRESTRS logic="or"> | ||
| 311 | > <SELRESTR Value="+" type="dir"/> | ||
| 312 | > <SELRESTR Value="+" type="src"/> | ||
| 313 | > <SELRESTR Value="+" type="dest_conf"/> | ||
| 314 | > </SELRESTRS> | ||
| 315 | diff /Users/hatkirby/Downloads/new_vn 2/push-12.xml datadir/vn/push-12.xml | ||
| 316 | 90c90,92 | ||
| 317 | < <SYNRESTRS/> | ||
| 318 | --- | ||
| 319 | > <SYNRESTRS> | ||
| 320 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 321 | > </SYNRESTRS> | ||
| 322 | diff /Users/hatkirby/Downloads/new_vn 2/roll-51.3.1.xml datadir/vn/roll-51.3.1.xml | ||
| 323 | 190c190,192 | ||
| 324 | < <SYNRESTRS/> | ||
| 325 | --- | ||
| 326 | > <SYNRESTRS> | ||
| 327 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 328 | > </SYNRESTRS> | ||
| 329 | 256c258,260 | ||
| 330 | < <SYNRESTRS/> | ||
| 331 | --- | ||
| 332 | > <SYNRESTRS> | ||
| 333 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 334 | > </SYNRESTRS> | ||
| 335 | diff /Users/hatkirby/Downloads/new_vn 2/see-30.1.xml datadir/vn/see-30.1.xml | ||
| 336 | 16a17,19 | ||
| 337 | > <THEMROLE type="Patient"> | ||
| 338 | > <SELRESTRS/> | ||
| 339 | > </THEMROLE> | ||
| 340 | 93a97,102 | ||
| 341 | > <PREP value="in"> | ||
| 342 | > <SELRESTRS/> | ||
| 343 | > </PREP> | ||
| 344 | > <NP value="Patient"> | ||
| 345 | > <SYNRESTRS/> | ||
| 346 | > </NP> | ||
| 347 | 231a241,243 | ||
| 348 | > <NP value="Patient"> | ||
| 349 | > <SYNRESTRS/> | ||
| 350 | > </NP> | ||
| 351 | diff /Users/hatkirby/Downloads/new_vn 2/seem-109.xml datadir/vn/seem-109.xml | ||
| 352 | 30,32c30,32 | ||
| 353 | < <SYNRESTRS> | ||
| 354 | < <SYNRESTR Value="-" type="sentential"/> | ||
| 355 | < </SYNRESTRS> | ||
| 356 | --- | ||
| 357 | > <SYNRESTRS> | ||
| 358 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 359 | > </SYNRESTRS> | ||
| 360 | diff /Users/hatkirby/Downloads/new_vn 2/slide-11.2.xml datadir/vn/slide-11.2.xml | ||
| 361 | 69,72c69,73 | ||
| 362 | < <SELRESTRS> | ||
| 363 | < <SELRESTR Value="+" type="path"/> | ||
| 364 | < <SELRESTR Value="-" type="dest_dir"/> | ||
| 365 | < </SELRESTRS> | ||
| 366 | --- | ||
| 367 | > <SELRESTRS logic="or"> | ||
| 368 | > <SELRESTR Value="+" type="dir"/> | ||
| 369 | > <SELRESTR Value="+" type="src"/> | ||
| 370 | > <SELRESTR Value="+" type="dest_conf"/> | ||
| 371 | > </SELRESTRS> | ||
| 372 | 218,221c219,223 | ||
| 373 | < <SELRESTRS> | ||
| 374 | < <SELRESTR Value="+" type="path"/> | ||
| 375 | < <SELRESTR Value="-" type="dest_dir"/> | ||
| 376 | < </SELRESTRS> | ||
| 377 | --- | ||
| 378 | > <SELRESTRS logic="or"> | ||
| 379 | > <SELRESTR Value="+" type="dir"/> | ||
| 380 | > <SELRESTR Value="+" type="src"/> | ||
| 381 | > <SELRESTR Value="+" type="dest_conf"/> | ||
| 382 | > </SELRESTRS> | ||
| 383 | diff /Users/hatkirby/Downloads/new_vn 2/spank-18.3.xml datadir/vn/spank-18.3.xml | ||
| 384 | 69a70,72 | ||
| 385 | > <THEMROLE type="Recipient"> | ||
| 386 | > <SELRESTRS/> | ||
| 387 | > </THEMROLE> | ||
| 388 | 201c204,206 | ||
| 389 | < <SYNRESTRS/> | ||
| 390 | --- | ||
| 391 | > <SYNRESTRS> | ||
| 392 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 393 | > </SYNRESTRS> | ||
| 394 | 529,532c534,541 | ||
| 395 | < <SYNRESTRS> | ||
| 396 | < <SYNRESTR Value="+" type="genitive"/> | ||
| 397 | < <SYNRESTR Value="+" type="body_part"/> | ||
| 398 | < </SYNRESTRS> | ||
| 399 | --- | ||
| 400 | > <SYNRESTRS> | ||
| 401 | > <SYNRESTR Value="+" type="genitive"/> | ||
| 402 | > </SYNRESTRS> | ||
| 403 | > </NP> | ||
| 404 | > <NP value="Recipient"> | ||
| 405 | > <SYNRESTRS> | ||
| 406 | > <SYNRESTR Value="+" type="body_part"/> | ||
| 407 | > </SYNRESTRS> | ||
| 408 | diff /Users/hatkirby/Downloads/new_vn 2/swat-18.2.xml datadir/vn/swat-18.2.xml | ||
| 409 | 264c264,266 | ||
| 410 | < <SYNRESTRS/> | ||
| 411 | --- | ||
| 412 | > <SYNRESTRS> | ||
| 413 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 414 | > </SYNRESTRS> | ||
| 415 | 324c326,328 | ||
| 416 | < <SYNRESTRS/> | ||
| 417 | --- | ||
| 418 | > <SYNRESTRS> | ||
| 419 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 420 | > </SYNRESTRS> | ||
| 421 | diff /Users/hatkirby/Downloads/new_vn 2/tape-22.4.xml datadir/vn/tape-22.4.xml | ||
| 422 | 364c364,366 | ||
| 423 | < <SYNRESTRS/> | ||
| 424 | --- | ||
| 425 | > <SYNRESTRS> | ||
| 426 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 427 | > </SYNRESTRS> | ||
| 428 | diff /Users/hatkirby/Downloads/new_vn 2/vehicle-51.4.1.xml datadir/vn/vehicle-51.4.1.xml | ||
| 429 | 227c227,229 | ||
| 430 | < <SYNRESTRS/> | ||
| 431 | --- | ||
| 432 | > <SYNRESTRS> | ||
| 433 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 434 | > </SYNRESTRS> | ||
| 435 | diff /Users/hatkirby/Downloads/new_vn 2/waltz-51.5.xml datadir/vn/waltz-51.5.xml | ||
| 436 | 181c181,183 | ||
| 437 | < <SYNRESTRS/> | ||
| 438 | --- | ||
| 439 | > <SYNRESTRS> | ||
| 440 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 441 | > </SYNRESTRS> | ||
| 442 | diff /Users/hatkirby/Downloads/new_vn 2/want-32.1.xml datadir/vn/want-32.1.xml | ||
| 443 | 142a143 | ||
| 444 | > <ADV/> | ||
| 445 | 194a196 | ||
| 446 | > <ADJ/> | ||
| 447 | 305a308 | ||
| 448 | > <LEX value="to be"/> | ||
| 449 | 307,309c310,312 | ||
| 450 | < <SYNRESTRS> | ||
| 451 | < <SYNRESTR Value="+" type="to_be"/> | ||
| 452 | < </SYNRESTRS> | ||
| 453 | --- | ||
| 454 | > <SYNRESTRS> | ||
| 455 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 456 | > </SYNRESTRS> | ||
| 457 | diff /Users/hatkirby/Downloads/new_vn 2/wipe_instr-10.4.2.xml datadir/vn/wipe_instr-10.4.2.xml | ||
| 458 | 178c178,180 | ||
| 459 | < <SYNRESTRS/> | ||
| 460 | --- | ||
| 461 | > <SYNRESTRS> | ||
| 462 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 463 | > </SYNRESTRS> | ||
| 464 | diff /Users/hatkirby/Downloads/new_vn 2/wipe_manner-10.4.1.xml datadir/vn/wipe_manner-10.4.1.xml | ||
| 465 | 198c198,199 | ||
| 466 | < <SELRESTR Value="-" type="region"/> | ||
| 467 | --- | ||
| 468 | > <SELRESTR Value="+" type="location"/> | ||
| 469 | > <SELRESTR Value="-" type="region"/> | ||
| 470 | diff /Users/hatkirby/Downloads/new_vn 2/wish-62.xml datadir/vn/wish-62.xml | ||
| 471 | 91a92 | ||
| 472 | > <LEX value="to be"/> | ||
| 473 | 93,95c94,96 | ||
| 474 | < <SYNRESTRS> | ||
| 475 | < <SYNRESTR Value="+" type="to_be"/> | ||
| 476 | < </SYNRESTRS> | ||
| 477 | --- | ||
| 478 | > <SYNRESTRS> | ||
| 479 | > <SYNRESTR Value="+" type="adjp"/> | ||
| 480 | > </SYNRESTRS> | ||
| 481 | 122a124 | ||
| 482 | > <ADJ/> | ||
| 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 @@ | |||
| 2 | 2 | ||
| 3 | namespace verbly { | 3 | namespace verbly { |
| 4 | 4 | ||
| 5 | adjective::adjective() | ||
| 6 | { | ||
| 7 | |||
| 8 | } | ||
| 9 | |||
| 5 | adjective::adjective(const data& _data, int _id) : word(_data, _id) | 10 | adjective::adjective(const data& _data, int _id) : word(_data, _id) |
| 6 | { | 11 | { |
| 7 | 12 | ||
| @@ -9,682 +14,100 @@ namespace verbly { | |||
| 9 | 14 | ||
| 10 | std::string adjective::base_form() const | 15 | std::string adjective::base_form() const |
| 11 | { | 16 | { |
| 17 | assert(_valid == true); | ||
| 18 | |||
| 12 | return _base_form; | 19 | return _base_form; |
| 13 | } | 20 | } |
| 14 | 21 | ||
| 15 | std::string adjective::comparative_form() const | 22 | std::string adjective::comparative_form() const |
| 16 | { | 23 | { |
| 24 | assert(_valid == true); | ||
| 25 | |||
| 17 | return _comparative_form; | 26 | return _comparative_form; |
| 18 | } | 27 | } |
| 19 | 28 | ||
| 20 | std::string adjective::superlative_form() const | 29 | std::string adjective::superlative_form() const |
| 21 | { | 30 | { |
| 31 | assert(_valid == true); | ||
| 32 | |||
| 22 | return _superlative_form; | 33 | return _superlative_form; |
| 23 | } | 34 | } |
| 24 | 35 | ||
| 25 | adjective::positioning adjective::position() const | 36 | adjective::positioning adjective::position() const |
| 26 | { | 37 | { |
| 38 | assert(_valid == true); | ||
| 39 | |||
| 27 | return _position; | 40 | return _position; |
| 28 | } | 41 | } |
| 29 | 42 | ||
| 30 | bool adjective::has_comparative_form() const | 43 | bool adjective::has_comparative_form() const |
| 31 | { | 44 | { |
| 45 | assert(_valid == true); | ||
| 46 | |||
| 32 | return !_comparative_form.empty(); | 47 | return !_comparative_form.empty(); |
| 33 | } | 48 | } |
| 34 | 49 | ||
| 35 | bool adjective::has_superlative_form() const | 50 | bool adjective::has_superlative_form() const |
| 36 | { | 51 | { |
| 52 | assert(_valid == true); | ||
| 53 | |||
| 37 | return !_superlative_form.empty(); | 54 | return !_superlative_form.empty(); |
| 38 | } | 55 | } |
| 39 | 56 | ||
| 40 | bool adjective::has_position() const | 57 | bool adjective::has_position() const |
| 41 | { | 58 | { |
| 59 | assert(_valid == true); | ||
| 60 | |||
| 42 | return _position != adjective::positioning::undefined; | 61 | return _position != adjective::positioning::undefined; |
| 43 | } | 62 | } |
| 44 | 63 | ||
| 45 | adjective_query adjective::antonyms() const | 64 | adjective_query adjective::antonyms() const |
| 46 | { | 65 | { |
| 47 | return _data.adjectives().antonym_of(*this); | 66 | assert(_valid == true); |
| 48 | } | ||
| 49 | |||
| 50 | adjective_query adjective::synonyms() const | ||
| 51 | { | ||
| 52 | return _data.adjectives().synonym_of(*this); | ||
| 53 | } | ||
| 54 | |||
| 55 | adjective_query adjective::generalizations() const | ||
| 56 | { | ||
| 57 | return _data.adjectives().generalization_of(*this); | ||
| 58 | } | ||
| 59 | |||
| 60 | adjective_query adjective::specifications() const | ||
| 61 | { | ||
| 62 | return _data.adjectives().specification_of(*this); | ||
| 63 | } | ||
| 64 | |||
| 65 | noun_query adjective::anti_pertainyms() const | ||
| 66 | { | ||
| 67 | return _data.nouns().anti_pertainym_of(*this); | ||
| 68 | } | ||
| 69 | |||
| 70 | adverb_query adjective::mannernyms() const | ||
| 71 | { | ||
| 72 | return _data.adverbs().mannernym_of(*this); | ||
| 73 | } | ||
| 74 | |||
| 75 | noun_query adjective::attributes() const | ||
| 76 | { | ||
| 77 | return _data.nouns().attribute_of(*this); | ||
| 78 | } | ||
| 79 | |||
| 80 | adjective_query::adjective_query(const data& _data) : _data(_data) | ||
| 81 | { | ||
| 82 | |||
| 83 | } | ||
| 84 | |||
| 85 | adjective_query& adjective_query::limit(int _limit) | ||
| 86 | { | ||
| 87 | if ((_limit > 0) || (_limit == unlimited)) | ||
| 88 | { | ||
| 89 | this->_limit = _limit; | ||
| 90 | } | ||
| 91 | |||
| 92 | return *this; | ||
| 93 | } | ||
| 94 | |||
| 95 | adjective_query& adjective_query::random(bool _random) | ||
| 96 | { | ||
| 97 | this->_random = _random; | ||
| 98 | |||
| 99 | return *this; | ||
| 100 | } | ||
| 101 | |||
| 102 | adjective_query& adjective_query::except(const adjective& _word) | ||
| 103 | { | ||
| 104 | _except.push_back(_word); | ||
| 105 | |||
| 106 | return *this; | ||
| 107 | } | ||
| 108 | |||
| 109 | adjective_query& adjective_query::rhymes_with(const word& _word) | ||
| 110 | { | ||
| 111 | for (auto rhyme : _word.rhyme_phonemes()) | ||
| 112 | { | ||
| 113 | _rhymes.push_back(rhyme); | ||
| 114 | } | ||
| 115 | |||
| 116 | if (dynamic_cast<const adjective*>(&_word) != nullptr) | ||
| 117 | { | ||
| 118 | _except.push_back(dynamic_cast<const adjective&>(_word)); | ||
| 119 | } | ||
| 120 | |||
| 121 | return *this; | ||
| 122 | } | ||
| 123 | |||
| 124 | adjective_query& adjective_query::has_pronunciation(bool _has_prn) | ||
| 125 | { | ||
| 126 | this->_has_prn = _has_prn; | ||
| 127 | |||
| 128 | return *this; | ||
| 129 | } | ||
| 130 | |||
| 131 | adjective_query& adjective_query::is_variant(bool _is_variant) | ||
| 132 | { | ||
| 133 | this->_is_variant = _is_variant; | ||
| 134 | |||
| 135 | return *this; | ||
| 136 | } | ||
| 137 | |||
| 138 | adjective_query& adjective_query::variant_of(const noun& _noun) | ||
| 139 | { | ||
| 140 | _variant_of.push_back(_noun); | ||
| 141 | |||
| 142 | return *this; | ||
| 143 | } | ||
| 144 | |||
| 145 | adjective_query& adjective_query::not_variant_of(const noun& _noun) | ||
| 146 | { | ||
| 147 | _not_variant_of.push_back(_noun); | ||
| 148 | |||
| 149 | return *this; | ||
| 150 | } | ||
| 151 | |||
| 152 | adjective_query& adjective_query::has_antonyms(bool _is_antonymic) | ||
| 153 | { | ||
| 154 | this->_is_antonymic = _is_antonymic; | ||
| 155 | |||
| 156 | return *this; | ||
| 157 | } | ||
| 158 | |||
| 159 | adjective_query& adjective_query::antonym_of(const adjective& _adj) | ||
| 160 | { | ||
| 161 | _antonym_of.push_back(_adj); | ||
| 162 | |||
| 163 | return *this; | ||
| 164 | } | ||
| 165 | |||
| 166 | adjective_query& adjective_query::not_antonym_of(const adjective& _adj) | ||
| 167 | { | ||
| 168 | _not_antonym_of.push_back(_adj); | ||
| 169 | |||
| 170 | return *this; | ||
| 171 | } | ||
| 172 | |||
| 173 | adjective_query& adjective_query::has_synonyms(bool _is_synonymic) | ||
| 174 | { | ||
| 175 | this->_is_synonymic = _is_synonymic; | ||
| 176 | |||
| 177 | return *this; | ||
| 178 | } | ||
| 179 | |||
| 180 | adjective_query& adjective_query::synonym_of(const adjective& _adj) | ||
| 181 | { | ||
| 182 | _synonym_of.push_back(_adj); | ||
| 183 | |||
| 184 | return *this; | ||
| 185 | } | ||
| 186 | |||
| 187 | adjective_query& adjective_query::not_synonym_of(const adjective& _adj) | ||
| 188 | { | ||
| 189 | _not_synonym_of.push_back(_adj); | ||
| 190 | |||
| 191 | return *this; | ||
| 192 | } | ||
| 193 | |||
| 194 | adjective_query& adjective_query::is_generalization(bool _is_generalization) | ||
| 195 | { | ||
| 196 | this->_is_generalization = _is_generalization; | ||
| 197 | |||
| 198 | return *this; | ||
| 199 | } | ||
| 200 | |||
| 201 | adjective_query& adjective_query::generalization_of(const adjective& _adj) | ||
| 202 | { | ||
| 203 | _generalization_of.push_back(_adj); | ||
| 204 | |||
| 205 | return *this; | ||
| 206 | } | ||
| 207 | |||
| 208 | adjective_query& adjective_query::not_generalization_of(const adjective& _adj) | ||
| 209 | { | ||
| 210 | _not_generalization_of.push_back(_adj); | ||
| 211 | |||
| 212 | return *this; | ||
| 213 | } | ||
| 214 | |||
| 215 | adjective_query& adjective_query::is_specification(bool _is_specification) | ||
| 216 | { | ||
| 217 | this->_is_specification = _is_specification; | ||
| 218 | |||
| 219 | return *this; | ||
| 220 | } | ||
| 221 | |||
| 222 | adjective_query& adjective_query::specification_of(const adjective& _adj) | ||
| 223 | { | ||
| 224 | _specification_of.push_back(_adj); | ||
| 225 | 67 | ||
| 226 | return *this; | 68 | return _data->adjectives().antonym_of(*this); |
| 227 | } | 69 | } |
| 228 | 70 | ||
| 229 | adjective_query& adjective_query::not_specification_of(const adjective& _adj) | 71 | adjective_query adjective::synonyms() const |
| 230 | { | ||
| 231 | _not_specification_of.push_back(_adj); | ||
| 232 | |||
| 233 | return *this; | ||
| 234 | } | ||
| 235 | |||
| 236 | adjective_query& adjective_query::is_pertainymic(bool _is_pertainymic) | ||
| 237 | { | ||
| 238 | this->_is_pertainymic = _is_pertainymic; | ||
| 239 | |||
| 240 | return *this; | ||
| 241 | } | ||
| 242 | |||
| 243 | adjective_query& adjective_query::pertainym_of(const noun& _noun) | ||
| 244 | { | 72 | { |
| 245 | _pertainym_of.push_back(_noun); | 73 | assert(_valid == true); |
| 246 | 74 | ||
| 247 | return *this; | 75 | return _data->adjectives().synonym_of(*this); |
| 248 | } | 76 | } |
| 249 | 77 | ||
| 250 | adjective_query& adjective_query::is_mannernymic(bool _is_mannernymic) | 78 | adjective_query adjective::generalizations() const |
| 251 | { | 79 | { |
| 252 | this->_is_mannernymic = _is_mannernymic; | 80 | assert(_valid == true); |
| 253 | 81 | ||
| 254 | return *this; | 82 | return _data->adjectives().generalization_of(*this); |
| 255 | } | 83 | } |
| 256 | 84 | ||
| 257 | adjective_query& adjective_query::anti_mannernym_of(const adverb& _adv) | 85 | adjective_query adjective::specifications() const |
| 258 | { | 86 | { |
| 259 | _anti_mannernym_of.push_back(_adv); | 87 | assert(_valid == true); |
| 260 | 88 | ||
| 261 | return *this; | 89 | return _data->adjectives().specification_of(*this); |
| 262 | } | 90 | } |
| 263 | 91 | ||
| 264 | adjective_query& adjective_query::derived_from(const word& _w) | 92 | noun_query adjective::anti_pertainyms() const |
| 265 | { | 93 | { |
| 266 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 94 | assert(_valid == true); |
| 267 | { | ||
| 268 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 269 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 270 | { | ||
| 271 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 272 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 273 | { | ||
| 274 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 275 | } | ||
| 276 | 95 | ||
| 277 | return *this; | 96 | return _data->nouns().anti_pertainym_of(*this); |
| 278 | } | 97 | } |
| 279 | 98 | ||
| 280 | adjective_query& adjective_query::not_derived_from(const word& _w) | 99 | adverb_query adjective::mannernyms() const |
| 281 | { | 100 | { |
| 282 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 101 | assert(_valid == true); |
| 283 | { | ||
| 284 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 285 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 286 | { | ||
| 287 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 288 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 289 | { | ||
| 290 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 291 | } | ||
| 292 | 102 | ||
| 293 | return *this; | 103 | return _data->adverbs().mannernym_of(*this); |
| 294 | } | 104 | } |
| 295 | 105 | ||
| 296 | std::list<adjective> adjective_query::run() const | 106 | noun_query adjective::attributes() const |
| 297 | { | 107 | { |
| 298 | std::stringstream construct; | 108 | assert(_valid == true); |
| 299 | construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; | ||
| 300 | std::list<std::string> conditions; | ||
| 301 | |||
| 302 | if (_has_prn) | ||
| 303 | { | ||
| 304 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM adjective_pronunciations)"); | ||
| 305 | } | ||
| 306 | |||
| 307 | if (!_rhymes.empty()) | ||
| 308 | { | ||
| 309 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
| 310 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 311 | conditions.push_back(cond); | ||
| 312 | } | ||
| 313 | |||
| 314 | for (auto except : _except) | ||
| 315 | { | ||
| 316 | conditions.push_back("adjective_id != @EXCID"); | ||
| 317 | } | ||
| 318 | |||
| 319 | if (_requires_comparative_form) | ||
| 320 | { | ||
| 321 | conditions.push_back("comparative IS NOT NULL"); | ||
| 322 | } | ||
| 323 | |||
| 324 | if (_requires_superlative_form) | ||
| 325 | { | ||
| 326 | conditions.push_back("superlative IS NOT NULL"); | ||
| 327 | } | ||
| 328 | |||
| 329 | if (_position != adjective::positioning::undefined) | ||
| 330 | { | ||
| 331 | switch (_position) | ||
| 332 | { | ||
| 333 | case adjective::positioning::predicate: conditions.push_back("position = 'p'"); break; | ||
| 334 | case adjective::positioning::attributive: conditions.push_back("position = 'a'"); break; | ||
| 335 | case adjective::positioning::postnominal: conditions.push_back("position = 'i'"); break; | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | if (_is_variant) | ||
| 340 | { | ||
| 341 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)"); | ||
| 342 | } | ||
| 343 | |||
| 344 | if (!_variant_of.empty()) | ||
| 345 | { | ||
| 346 | std::list<std::string> clauses(_variant_of.size(), "noun_id = @ATTRID"); | ||
| 347 | std::string cond = "adjective_id IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 348 | conditions.push_back(cond); | ||
| 349 | } | ||
| 350 | |||
| 351 | if (!_not_variant_of.empty()) | ||
| 352 | { | ||
| 353 | std::list<std::string> clauses(_not_variant_of.size(), "noun_id = @NATTRID"); | ||
| 354 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 355 | conditions.push_back(cond); | ||
| 356 | } | ||
| 357 | |||
| 358 | if (_is_antonymic) | ||
| 359 | { | ||
| 360 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); | ||
| 361 | } | ||
| 362 | |||
| 363 | if (!_antonym_of.empty()) | ||
| 364 | { | ||
| 365 | std::list<std::string> clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); | ||
| 366 | std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 367 | conditions.push_back(cond); | ||
| 368 | } | ||
| 369 | |||
| 370 | if (!_not_antonym_of.empty()) | ||
| 371 | { | ||
| 372 | std::list<std::string> clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); | ||
| 373 | std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 374 | conditions.push_back(cond); | ||
| 375 | } | ||
| 376 | 109 | ||
| 377 | if (_is_synonymic) | 110 | return _data->nouns().attribute_of(*this); |
| 378 | { | ||
| 379 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); | ||
| 380 | } | ||
| 381 | |||
| 382 | if (!_synonym_of.empty()) | ||
| 383 | { | ||
| 384 | std::list<std::string> clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); | ||
| 385 | std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 386 | conditions.push_back(cond); | ||
| 387 | } | ||
| 388 | |||
| 389 | if (!_not_synonym_of.empty()) | ||
| 390 | { | ||
| 391 | std::list<std::string> clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); | ||
| 392 | std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 393 | conditions.push_back(cond); | ||
| 394 | } | ||
| 395 | |||
| 396 | if (_is_generalization) | ||
| 397 | { | ||
| 398 | conditions.push_back("adjective_id IN (SELECT general_id FROM specification)"); | ||
| 399 | } | ||
| 400 | |||
| 401 | if (!_generalization_of.empty()) | ||
| 402 | { | ||
| 403 | std::list<std::string> clauses(_generalization_of.size(), "specific_id = @SPECID"); | ||
| 404 | std::string cond = "adjective_id IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 405 | conditions.push_back(cond); | ||
| 406 | } | ||
| 407 | |||
| 408 | if (!_not_generalization_of.empty()) | ||
| 409 | { | ||
| 410 | std::list<std::string> clauses(_not_generalization_of.size(), "specific_id = @NSPECID"); | ||
| 411 | std::string cond = "adjective_id NOT IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 412 | conditions.push_back(cond); | ||
| 413 | } | ||
| 414 | |||
| 415 | if (_is_specification) | ||
| 416 | { | ||
| 417 | conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)"); | ||
| 418 | } | ||
| 419 | |||
| 420 | if (!_specification_of.empty()) | ||
| 421 | { | ||
| 422 | std::list<std::string> clauses(_specification_of.size(), "general_id = @GENID"); | ||
| 423 | std::string cond = "adjective_id IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 424 | conditions.push_back(cond); | ||
| 425 | } | ||
| 426 | |||
| 427 | if (!_not_specification_of.empty()) | ||
| 428 | { | ||
| 429 | std::list<std::string> clauses(_not_specification_of.size(), "general_id = @NGENID"); | ||
| 430 | std::string cond = "adjective_id NOT IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 431 | conditions.push_back(cond); | ||
| 432 | } | ||
| 433 | |||
| 434 | if (_is_pertainymic) | ||
| 435 | { | ||
| 436 | conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)"); | ||
| 437 | } | ||
| 438 | |||
| 439 | if (!_pertainym_of.empty()) | ||
| 440 | { | ||
| 441 | std::list<std::string> clauses(_pertainym_of.size(), "noun_id = @APERID"); | ||
| 442 | std::string cond = "adjective_id IN (SELECT pertainym_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 443 | conditions.push_back(cond); | ||
| 444 | } | ||
| 445 | |||
| 446 | if (_is_mannernymic) | ||
| 447 | { | ||
| 448 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)"); | ||
| 449 | } | ||
| 450 | |||
| 451 | if (!_anti_mannernym_of.empty()) | ||
| 452 | { | ||
| 453 | std::list<std::string> clauses(_anti_mannernym_of.size(), "mannernym_id = @MANID"); | ||
| 454 | std::string cond = "adjective_id IN (SELECT adjective_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 455 | conditions.push_back(cond); | ||
| 456 | } | ||
| 457 | |||
| 458 | if (!_derived_from_adjective.empty()) | ||
| 459 | { | ||
| 460 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_2_id = @DERADJ"); | ||
| 461 | std::string cond = "adjective_id IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 462 | conditions.push_back(cond); | ||
| 463 | } | ||
| 464 | |||
| 465 | if (!_not_derived_from_adjective.empty()) | ||
| 466 | { | ||
| 467 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_2_id = @NDERADJ"); | ||
| 468 | 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 ") + ")"; | ||
| 469 | conditions.push_back(cond); | ||
| 470 | } | ||
| 471 | |||
| 472 | if (!_derived_from_adverb.empty()) | ||
| 473 | { | ||
| 474 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); | ||
| 475 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 476 | conditions.push_back(cond); | ||
| 477 | } | ||
| 478 | |||
| 479 | if (!_not_derived_from_adverb.empty()) | ||
| 480 | { | ||
| 481 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); | ||
| 482 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 483 | conditions.push_back(cond); | ||
| 484 | } | ||
| 485 | |||
| 486 | if (!_derived_from_noun.empty()) | ||
| 487 | { | ||
| 488 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN"); | ||
| 489 | std::string cond = "adjective_id IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 490 | conditions.push_back(cond); | ||
| 491 | } | ||
| 492 | |||
| 493 | if (!_not_derived_from_noun.empty()) | ||
| 494 | { | ||
| 495 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); | ||
| 496 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 497 | conditions.push_back(cond); | ||
| 498 | } | ||
| 499 | |||
| 500 | if (!conditions.empty()) | ||
| 501 | { | ||
| 502 | construct << " WHERE "; | ||
| 503 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
| 504 | } | ||
| 505 | |||
| 506 | if (_random) | ||
| 507 | { | ||
| 508 | construct << " ORDER BY RANDOM()"; | ||
| 509 | } | ||
| 510 | |||
| 511 | if (_limit != unlimited) | ||
| 512 | { | ||
| 513 | construct << " LIMIT " << _limit; | ||
| 514 | } | ||
| 515 | |||
| 516 | sqlite3_stmt* ppstmt; | ||
| 517 | std::string query = construct.str(); | ||
| 518 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 519 | { | ||
| 520 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 521 | } | ||
| 522 | |||
| 523 | if (!_rhymes.empty()) | ||
| 524 | { | ||
| 525 | int i = 0; | ||
| 526 | for (auto rhyme : _rhymes) | ||
| 527 | { | ||
| 528 | std::string rhymer = "%" + rhyme; | ||
| 529 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
| 530 | |||
| 531 | i++; | ||
| 532 | } | ||
| 533 | } | ||
| 534 | |||
| 535 | for (auto except : _except) | ||
| 536 | { | ||
| 537 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
| 538 | } | ||
| 539 | |||
| 540 | for (auto attribute : _variant_of) | ||
| 541 | { | ||
| 542 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ATTRID"), attribute._id); | ||
| 543 | } | ||
| 544 | |||
| 545 | for (auto attribute : _not_variant_of) | ||
| 546 | { | ||
| 547 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NATTRID"), attribute._id); | ||
| 548 | } | ||
| 549 | |||
| 550 | for (auto antonym : _antonym_of) | ||
| 551 | { | ||
| 552 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
| 553 | } | ||
| 554 | |||
| 555 | for (auto antonym : _not_antonym_of) | ||
| 556 | { | ||
| 557 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
| 558 | } | ||
| 559 | |||
| 560 | for (auto synonym : _synonym_of) | ||
| 561 | { | ||
| 562 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
| 563 | } | ||
| 564 | |||
| 565 | for (auto synonym : _not_synonym_of) | ||
| 566 | { | ||
| 567 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
| 568 | } | ||
| 569 | |||
| 570 | for (auto specific : _generalization_of) | ||
| 571 | { | ||
| 572 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SPECID"), specific._id); | ||
| 573 | } | ||
| 574 | |||
| 575 | for (auto specific : _not_generalization_of) | ||
| 576 | { | ||
| 577 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSPECID"), specific._id); | ||
| 578 | } | ||
| 579 | |||
| 580 | for (auto general : _specification_of) | ||
| 581 | { | ||
| 582 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GENID"), general._id); | ||
| 583 | } | ||
| 584 | |||
| 585 | for (auto general : _not_specification_of) | ||
| 586 | { | ||
| 587 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NGENID"), general._id); | ||
| 588 | } | ||
| 589 | |||
| 590 | for (auto n : _pertainym_of) | ||
| 591 | { | ||
| 592 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@APERID"), n._id); | ||
| 593 | } | ||
| 594 | |||
| 595 | for (auto mannernym : _anti_mannernym_of) | ||
| 596 | { | ||
| 597 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MANID"), mannernym._id); | ||
| 598 | } | ||
| 599 | |||
| 600 | for (auto adj : _derived_from_adjective) | ||
| 601 | { | ||
| 602 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
| 603 | } | ||
| 604 | |||
| 605 | for (auto adj : _not_derived_from_adjective) | ||
| 606 | { | ||
| 607 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
| 608 | } | ||
| 609 | |||
| 610 | for (auto adv : _derived_from_adverb) | ||
| 611 | { | ||
| 612 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
| 613 | } | ||
| 614 | |||
| 615 | for (auto adv : _not_derived_from_adverb) | ||
| 616 | { | ||
| 617 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
| 618 | } | ||
| 619 | |||
| 620 | for (auto n : _derived_from_noun) | ||
| 621 | { | ||
| 622 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
| 623 | } | ||
| 624 | |||
| 625 | for (auto n : _not_derived_from_noun) | ||
| 626 | { | ||
| 627 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
| 628 | } | ||
| 629 | |||
| 630 | std::list<adjective> output; | ||
| 631 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 632 | { | ||
| 633 | adjective tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
| 634 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
| 635 | |||
| 636 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
| 637 | { | ||
| 638 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
| 639 | } | ||
| 640 | |||
| 641 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
| 642 | { | ||
| 643 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
| 644 | } | ||
| 645 | |||
| 646 | if (sqlite3_column_type(ppstmt, 4) != SQLITE_NULL) | ||
| 647 | { | ||
| 648 | std::string adjpos(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
| 649 | if (adjpos == "p") | ||
| 650 | { | ||
| 651 | tnc._position = adjective::positioning::predicate; | ||
| 652 | } else if (adjpos == "a") | ||
| 653 | { | ||
| 654 | tnc._position = adjective::positioning::attributive; | ||
| 655 | } else if (adjpos == "i") | ||
| 656 | { | ||
| 657 | tnc._position = adjective::positioning::postnominal; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | |||
| 661 | output.push_back(tnc); | ||
| 662 | } | ||
| 663 | |||
| 664 | sqlite3_finalize(ppstmt); | ||
| 665 | |||
| 666 | for (auto& adjective : output) | ||
| 667 | { | ||
| 668 | query = "SELECT pronunciation FROM adjective_pronunciations WHERE adjective_id = ?"; | ||
| 669 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 670 | { | ||
| 671 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 672 | } | ||
| 673 | |||
| 674 | sqlite3_bind_int(ppstmt, 1, adjective._id); | ||
| 675 | |||
| 676 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 677 | { | ||
| 678 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 679 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
| 680 | |||
| 681 | adjective.pronunciations.push_back(phonemes); | ||
| 682 | } | ||
| 683 | |||
| 684 | sqlite3_finalize(ppstmt); | ||
| 685 | } | ||
| 686 | |||
| 687 | return output; | ||
| 688 | } | 111 | } |
| 689 | 112 | ||
| 690 | }; | 113 | }; |
| 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 { | |||
| 25 | friend class adjective_query; | 25 | friend class adjective_query; |
| 26 | 26 | ||
| 27 | public: | 27 | public: |
| 28 | adjective(); | ||
| 28 | adjective(const data& _data, int _id); | 29 | adjective(const data& _data, int _id); |
| 29 | 30 | ||
| 30 | std::string base_form() const; | 31 | std::string base_form() const; |
| @@ -45,99 +46,6 @@ namespace verbly { | |||
| 45 | noun_query attributes() const; | 46 | noun_query attributes() const; |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 48 | class adjective_query { | ||
| 49 | public: | ||
| 50 | adjective_query(const data& _data); | ||
| 51 | |||
| 52 | adjective_query& limit(int _limit); | ||
| 53 | adjective_query& random(bool _random); | ||
| 54 | adjective_query& except(const adjective& _word); | ||
| 55 | adjective_query& rhymes_with(const word& _word); | ||
| 56 | adjective_query& has_pronunciation(bool _has_prn); | ||
| 57 | |||
| 58 | adjective_query& requires_comparative_form(bool req); | ||
| 59 | adjective_query& requires_superlative_form(bool req); | ||
| 60 | adjective_query& position(adjective::positioning pos); | ||
| 61 | |||
| 62 | adjective_query& is_variant(bool _is_variant); | ||
| 63 | adjective_query& variant_of(const noun& _noun); | ||
| 64 | adjective_query& not_variant_of(const noun& _noun); | ||
| 65 | |||
| 66 | adjective_query& has_antonyms(bool _is_antonymic); | ||
| 67 | adjective_query& antonym_of(const adjective& _adj); | ||
| 68 | adjective_query& not_antonym_of(const adjective& _adj); | ||
| 69 | |||
| 70 | adjective_query& has_synonyms(bool _is_synonymic); | ||
| 71 | adjective_query& synonym_of(const adjective& _adj); | ||
| 72 | adjective_query& not_synonym_of(const adjective& _adj); | ||
| 73 | |||
| 74 | adjective_query& is_generalization(bool _is_generalization); | ||
| 75 | adjective_query& generalization_of(const adjective& _adj); | ||
| 76 | adjective_query& not_generalization_of(const adjective& _adj); | ||
| 77 | |||
| 78 | adjective_query& is_specification(bool _is_specification); | ||
| 79 | adjective_query& specification_of(const adjective& _adj); | ||
| 80 | adjective_query& not_specification_of(const adjective& _adj); | ||
| 81 | |||
| 82 | adjective_query& is_pertainymic(bool _is_pertainymic); | ||
| 83 | adjective_query& pertainym_of(const noun& _noun); | ||
| 84 | |||
| 85 | adjective_query& is_mannernymic(bool _is_mannernymic); | ||
| 86 | adjective_query& anti_mannernym_of(const adverb& _adv); | ||
| 87 | |||
| 88 | adjective_query& derived_from(const word& _w); | ||
| 89 | adjective_query& not_derived_from(const word& _w); | ||
| 90 | |||
| 91 | std::list<adjective> run() const; | ||
| 92 | |||
| 93 | const static int unlimited = -1; | ||
| 94 | |||
| 95 | protected: | ||
| 96 | const data& _data; | ||
| 97 | int _limit = unlimited; | ||
| 98 | bool _random = false; | ||
| 99 | std::list<std::string> _rhymes; | ||
| 100 | std::list<adjective> _except; | ||
| 101 | bool _has_prn = false; | ||
| 102 | |||
| 103 | bool _requires_comparative_form = false; | ||
| 104 | bool _requires_superlative_form = false; | ||
| 105 | adjective::positioning _position = adjective::positioning::undefined; | ||
| 106 | |||
| 107 | bool _is_variant = false; | ||
| 108 | std::list<noun> _variant_of; | ||
| 109 | std::list<noun> _not_variant_of; | ||
| 110 | |||
| 111 | bool _is_antonymic = false; | ||
| 112 | std::list<adjective> _antonym_of; | ||
| 113 | std::list<adjective> _not_antonym_of; | ||
| 114 | |||
| 115 | bool _is_synonymic = false; | ||
| 116 | std::list<adjective> _synonym_of; | ||
| 117 | std::list<adjective> _not_synonym_of; | ||
| 118 | |||
| 119 | bool _is_generalization = false; | ||
| 120 | std::list<adjective> _generalization_of; | ||
| 121 | std::list<adjective> _not_generalization_of; | ||
| 122 | |||
| 123 | bool _is_specification = false; | ||
| 124 | std::list<adjective> _specification_of; | ||
| 125 | std::list<adjective> _not_specification_of; | ||
| 126 | |||
| 127 | bool _is_pertainymic = false; | ||
| 128 | std::list<noun> _pertainym_of; | ||
| 129 | |||
| 130 | bool _is_mannernymic = false; | ||
| 131 | std::list<adverb> _anti_mannernym_of; | ||
| 132 | |||
| 133 | std::list<adjective> _derived_from_adjective; | ||
| 134 | std::list<adjective> _not_derived_from_adjective; | ||
| 135 | std::list<adverb> _derived_from_adverb; | ||
| 136 | std::list<adverb> _not_derived_from_adverb; | ||
| 137 | std::list<noun> _derived_from_noun; | ||
| 138 | std::list<noun> _not_derived_from_noun; | ||
| 139 | }; | ||
| 140 | |||
| 141 | }; | 49 | }; |
| 142 | 50 | ||
| 143 | #endif /* end of include guard: ADJECTIVE_H_87B3FB75 */ | 51 | #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 @@ | |||
| 1 | #include "verbly.h" | ||
| 2 | |||
| 3 | namespace verbly { | ||
| 4 | |||
| 5 | adjective_query::adjective_query(const data& _data) : _data(_data) | ||
| 6 | { | ||
| 7 | |||
| 8 | } | ||
| 9 | |||
| 10 | adjective_query& adjective_query::limit(int _limit) | ||
| 11 | { | ||
| 12 | if ((_limit > 0) || (_limit == unlimited)) | ||
| 13 | { | ||
| 14 | this->_limit = _limit; | ||
| 15 | } | ||
| 16 | |||
| 17 | return *this; | ||
| 18 | } | ||
| 19 | |||
| 20 | adjective_query& adjective_query::random() | ||
| 21 | { | ||
| 22 | this->_random = true; | ||
| 23 | |||
| 24 | return *this; | ||
| 25 | } | ||
| 26 | |||
| 27 | adjective_query& adjective_query::except(const adjective& _word) | ||
| 28 | { | ||
| 29 | _except.push_back(_word); | ||
| 30 | |||
| 31 | return *this; | ||
| 32 | } | ||
| 33 | |||
| 34 | adjective_query& adjective_query::rhymes_with(const word& _word) | ||
| 35 | { | ||
| 36 | for (auto rhyme : _word.rhyme_phonemes()) | ||
| 37 | { | ||
| 38 | _rhymes.push_back(rhyme); | ||
| 39 | } | ||
| 40 | |||
| 41 | if (dynamic_cast<const adjective*>(&_word) != nullptr) | ||
| 42 | { | ||
| 43 | _except.push_back(dynamic_cast<const adjective&>(_word)); | ||
| 44 | } | ||
| 45 | |||
| 46 | return *this; | ||
| 47 | } | ||
| 48 | |||
| 49 | adjective_query& adjective_query::has_pronunciation() | ||
| 50 | { | ||
| 51 | this->_has_prn = true; | ||
| 52 | |||
| 53 | return *this; | ||
| 54 | } | ||
| 55 | |||
| 56 | adjective_query& adjective_query::is_variant() | ||
| 57 | { | ||
| 58 | this->_is_variant = true; | ||
| 59 | |||
| 60 | return *this; | ||
| 61 | } | ||
| 62 | |||
| 63 | adjective_query& adjective_query::variant_of(filter<noun> _f) | ||
| 64 | { | ||
| 65 | _f.clean(); | ||
| 66 | _variant_of = _f; | ||
| 67 | |||
| 68 | return *this; | ||
| 69 | } | ||
| 70 | |||
| 71 | adjective_query& adjective_query::has_antonyms() | ||
| 72 | { | ||
| 73 | this->_is_antonymic = true; | ||
| 74 | |||
| 75 | return *this; | ||
| 76 | } | ||
| 77 | |||
| 78 | adjective_query& adjective_query::antonym_of(filter<adjective> _f) | ||
| 79 | { | ||
| 80 | _f.clean(); | ||
| 81 | _antonym_of = _f; | ||
| 82 | |||
| 83 | return *this; | ||
| 84 | } | ||
| 85 | |||
| 86 | adjective_query& adjective_query::has_synonyms() | ||
| 87 | { | ||
| 88 | this->_is_synonymic = true; | ||
| 89 | |||
| 90 | return *this; | ||
| 91 | } | ||
| 92 | |||
| 93 | adjective_query& adjective_query::synonym_of(filter<adjective> _f) | ||
| 94 | { | ||
| 95 | _f.clean(); | ||
| 96 | _synonym_of = _f; | ||
| 97 | |||
| 98 | return *this; | ||
| 99 | } | ||
| 100 | |||
| 101 | adjective_query& adjective_query::is_generalization() | ||
| 102 | { | ||
| 103 | this->_is_generalization = true; | ||
| 104 | |||
| 105 | return *this; | ||
| 106 | } | ||
| 107 | |||
| 108 | adjective_query& adjective_query::generalization_of(filter<adjective> _f) | ||
| 109 | { | ||
| 110 | _f.clean(); | ||
| 111 | _generalization_of = _f; | ||
| 112 | |||
| 113 | return *this; | ||
| 114 | } | ||
| 115 | |||
| 116 | adjective_query& adjective_query::is_specification() | ||
| 117 | { | ||
| 118 | this->_is_specification = true; | ||
| 119 | |||
| 120 | return *this; | ||
| 121 | } | ||
| 122 | |||
| 123 | adjective_query& adjective_query::specification_of(filter<adjective> _f) | ||
| 124 | { | ||
| 125 | _f.clean(); | ||
| 126 | _specification_of = _f; | ||
| 127 | |||
| 128 | return *this; | ||
| 129 | } | ||
| 130 | |||
| 131 | adjective_query& adjective_query::is_pertainymic() | ||
| 132 | { | ||
| 133 | this->_is_pertainymic = true; | ||
| 134 | |||
| 135 | return *this; | ||
| 136 | } | ||
| 137 | |||
| 138 | adjective_query& adjective_query::pertainym_of(filter<noun> _f) | ||
| 139 | { | ||
| 140 | _f.clean(); | ||
| 141 | _pertainym_of = _f; | ||
| 142 | |||
| 143 | return *this; | ||
| 144 | } | ||
| 145 | |||
| 146 | adjective_query& adjective_query::is_mannernymic() | ||
| 147 | { | ||
| 148 | this->_is_mannernymic = true; | ||
| 149 | |||
| 150 | return *this; | ||
| 151 | } | ||
| 152 | |||
| 153 | adjective_query& adjective_query::anti_mannernym_of(filter<adverb> _f) | ||
| 154 | { | ||
| 155 | _f.clean(); | ||
| 156 | _anti_mannernym_of = _f; | ||
| 157 | |||
| 158 | return *this; | ||
| 159 | } | ||
| 160 | /* | ||
| 161 | adjective_query& adjective_query::derived_from(const word& _w) | ||
| 162 | { | ||
| 163 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
| 164 | { | ||
| 165 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 166 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 167 | { | ||
| 168 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 169 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 170 | { | ||
| 171 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 172 | } | ||
| 173 | |||
| 174 | return *this; | ||
| 175 | } | ||
| 176 | |||
| 177 | adjective_query& adjective_query::not_derived_from(const word& _w) | ||
| 178 | { | ||
| 179 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
| 180 | { | ||
| 181 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 182 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 183 | { | ||
| 184 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 185 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 186 | { | ||
| 187 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 188 | } | ||
| 189 | |||
| 190 | return *this; | ||
| 191 | } | ||
| 192 | */ | ||
| 193 | std::list<adjective> adjective_query::run() const | ||
| 194 | { | ||
| 195 | std::stringstream construct; | ||
| 196 | construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; | ||
| 197 | std::list<std::string> conditions; | ||
| 198 | |||
| 199 | if (_has_prn) | ||
| 200 | { | ||
| 201 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM adjective_pronunciations)"); | ||
| 202 | } | ||
| 203 | |||
| 204 | if (!_rhymes.empty()) | ||
| 205 | { | ||
| 206 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
| 207 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 208 | conditions.push_back(cond); | ||
| 209 | } | ||
| 210 | |||
| 211 | for (auto except : _except) | ||
| 212 | { | ||
| 213 | conditions.push_back("adjective_id != @EXCID"); | ||
| 214 | } | ||
| 215 | |||
| 216 | if (_requires_comparative_form) | ||
| 217 | { | ||
| 218 | conditions.push_back("comparative IS NOT NULL"); | ||
| 219 | } | ||
| 220 | |||
| 221 | if (_requires_superlative_form) | ||
| 222 | { | ||
| 223 | conditions.push_back("superlative IS NOT NULL"); | ||
| 224 | } | ||
| 225 | |||
| 226 | switch (_position) | ||
| 227 | { | ||
| 228 | case adjective::positioning::predicate: conditions.push_back("position = 'p'"); break; | ||
| 229 | case adjective::positioning::attributive: conditions.push_back("position = 'a'"); break; | ||
| 230 | case adjective::positioning::postnominal: conditions.push_back("position = 'i'"); break; | ||
| 231 | case adjective::positioning::undefined: break; | ||
| 232 | } | ||
| 233 | |||
| 234 | if (_is_variant) | ||
| 235 | { | ||
| 236 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)"); | ||
| 237 | } | ||
| 238 | |||
| 239 | if (!_variant_of.empty()) | ||
| 240 | { | ||
| 241 | std::stringstream cond; | ||
| 242 | if (_variant_of.get_notlogic()) | ||
| 243 | { | ||
| 244 | cond << "adjective_id NOT IN"; | ||
| 245 | } else { | ||
| 246 | cond << "adjective_id IN"; | ||
| 247 | } | ||
| 248 | |||
| 249 | cond << "(SELECT adjective_id FROM variation WHERE "; | ||
| 250 | |||
| 251 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 252 | switch (f.get_type()) | ||
| 253 | { | ||
| 254 | case filter<noun>::type::singleton: | ||
| 255 | { | ||
| 256 | if (notlogic == f.get_notlogic()) | ||
| 257 | { | ||
| 258 | return "noun_id = @ATTRID"; | ||
| 259 | } else { | ||
| 260 | return "noun_id != @ATTRID"; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | case filter<noun>::type::group: | ||
| 265 | { | ||
| 266 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 267 | |||
| 268 | std::list<std::string> clauses; | ||
| 269 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 270 | return recur(f2, truelogic); | ||
| 271 | }); | ||
| 272 | |||
| 273 | if (truelogic == f.get_orlogic()) | ||
| 274 | { | ||
| 275 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 276 | } else { | ||
| 277 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 278 | } | ||
| 279 | } | ||
| 280 | } | ||
| 281 | }; | ||
| 282 | |||
| 283 | cond << recur(_variant_of, _variant_of.get_notlogic()); | ||
| 284 | cond << ")"; | ||
| 285 | conditions.push_back(cond.str()); | ||
| 286 | } | ||
| 287 | |||
| 288 | if (_is_antonymic) | ||
| 289 | { | ||
| 290 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); | ||
| 291 | } | ||
| 292 | |||
| 293 | if (!_antonym_of.empty()) | ||
| 294 | { | ||
| 295 | std::stringstream cond; | ||
| 296 | if (_antonym_of.get_notlogic()) | ||
| 297 | { | ||
| 298 | cond << "adjective_id NOT IN"; | ||
| 299 | } else { | ||
| 300 | cond << "adjective_id IN"; | ||
| 301 | } | ||
| 302 | |||
| 303 | cond << "(SELECT adjective_2_id FROM adjective_antonymy WHERE "; | ||
| 304 | |||
| 305 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
| 306 | switch (f.get_type()) | ||
| 307 | { | ||
| 308 | case filter<adjective>::type::singleton: | ||
| 309 | { | ||
| 310 | if (notlogic == f.get_notlogic()) | ||
| 311 | { | ||
| 312 | return "adjective_1_id = @ANTID"; | ||
| 313 | } else { | ||
| 314 | return "adjective_1_id != @ANTID"; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | case filter<adjective>::type::group: | ||
| 319 | { | ||
| 320 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 321 | |||
| 322 | std::list<std::string> clauses; | ||
| 323 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
| 324 | return recur(f2, truelogic); | ||
| 325 | }); | ||
| 326 | |||
| 327 | if (truelogic == f.get_orlogic()) | ||
| 328 | { | ||
| 329 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 330 | } else { | ||
| 331 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 332 | } | ||
| 333 | } | ||
| 334 | } | ||
| 335 | }; | ||
| 336 | |||
| 337 | cond << recur(_antonym_of, _antonym_of.get_notlogic()); | ||
| 338 | cond << ")"; | ||
| 339 | conditions.push_back(cond.str()); | ||
| 340 | } | ||
| 341 | |||
| 342 | if (_is_synonymic) | ||
| 343 | { | ||
| 344 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); | ||
| 345 | } | ||
| 346 | |||
| 347 | if (!_synonym_of.empty()) | ||
| 348 | { | ||
| 349 | std::stringstream cond; | ||
| 350 | if (_synonym_of.get_notlogic()) | ||
| 351 | { | ||
| 352 | cond << "adjective_id NOT IN"; | ||
| 353 | } else { | ||
| 354 | cond << "adjective_id IN"; | ||
| 355 | } | ||
| 356 | |||
| 357 | cond << "(SELECT adjective_2_id FROM adjective_synonymy WHERE "; | ||
| 358 | |||
| 359 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
| 360 | switch (f.get_type()) | ||
| 361 | { | ||
| 362 | case filter<adjective>::type::singleton: | ||
| 363 | { | ||
| 364 | if (notlogic == f.get_notlogic()) | ||
| 365 | { | ||
| 366 | return "adjective_1_id = @SYNID"; | ||
| 367 | } else { | ||
| 368 | return "adjective_1_id != @SYNID"; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | case filter<adjective>::type::group: | ||
| 373 | { | ||
| 374 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 375 | |||
| 376 | std::list<std::string> clauses; | ||
| 377 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
| 378 | return recur(f2, truelogic); | ||
| 379 | }); | ||
| 380 | |||
| 381 | if (truelogic == f.get_orlogic()) | ||
| 382 | { | ||
| 383 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 384 | } else { | ||
| 385 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 386 | } | ||
| 387 | } | ||
| 388 | } | ||
| 389 | }; | ||
| 390 | |||
| 391 | cond << recur(_synonym_of, _synonym_of.get_notlogic()); | ||
| 392 | cond << ")"; | ||
| 393 | conditions.push_back(cond.str()); | ||
| 394 | } | ||
| 395 | |||
| 396 | if (_is_generalization) | ||
| 397 | { | ||
| 398 | conditions.push_back("adjective_id IN (SELECT general_id FROM specification)"); | ||
| 399 | } | ||
| 400 | |||
| 401 | if (!_generalization_of.empty()) | ||
| 402 | { | ||
| 403 | std::stringstream cond; | ||
| 404 | if (_generalization_of.get_notlogic()) | ||
| 405 | { | ||
| 406 | cond << "adjective_id NOT IN"; | ||
| 407 | } else { | ||
| 408 | cond << "adjective_id IN"; | ||
| 409 | } | ||
| 410 | |||
| 411 | cond << "(SELECT general_id FROM specification WHERE "; | ||
| 412 | |||
| 413 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
| 414 | switch (f.get_type()) | ||
| 415 | { | ||
| 416 | case filter<adjective>::type::singleton: | ||
| 417 | { | ||
| 418 | if (notlogic == f.get_notlogic()) | ||
| 419 | { | ||
| 420 | return "specific_id = @SPECID"; | ||
| 421 | } else { | ||
| 422 | return "specific_id != @SPECID"; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | |||
| 426 | case filter<adjective>::type::group: | ||
| 427 | { | ||
| 428 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 429 | |||
| 430 | std::list<std::string> clauses; | ||
| 431 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
| 432 | return recur(f2, truelogic); | ||
| 433 | }); | ||
| 434 | |||
| 435 | if (truelogic == f.get_orlogic()) | ||
| 436 | { | ||
| 437 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 438 | } else { | ||
| 439 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | } | ||
| 443 | }; | ||
| 444 | |||
| 445 | cond << recur(_generalization_of, _generalization_of.get_notlogic()); | ||
| 446 | cond << ")"; | ||
| 447 | conditions.push_back(cond.str()); | ||
| 448 | } | ||
| 449 | |||
| 450 | if (_is_specification) | ||
| 451 | { | ||
| 452 | conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)"); | ||
| 453 | } | ||
| 454 | |||
| 455 | if (!_specification_of.empty()) | ||
| 456 | { | ||
| 457 | std::stringstream cond; | ||
| 458 | if (_specification_of.get_notlogic()) | ||
| 459 | { | ||
| 460 | cond << "adjective_id NOT IN"; | ||
| 461 | } else { | ||
| 462 | cond << "adjective_id IN"; | ||
| 463 | } | ||
| 464 | |||
| 465 | cond << "(SELECT specific_id FROM specification WHERE "; | ||
| 466 | |||
| 467 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
| 468 | switch (f.get_type()) | ||
| 469 | { | ||
| 470 | case filter<adjective>::type::singleton: | ||
| 471 | { | ||
| 472 | if (notlogic == f.get_notlogic()) | ||
| 473 | { | ||
| 474 | return "general_id = @GENID"; | ||
| 475 | } else { | ||
| 476 | return "general_id != @GENID"; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | case filter<adjective>::type::group: | ||
| 481 | { | ||
| 482 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 483 | |||
| 484 | std::list<std::string> clauses; | ||
| 485 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
| 486 | return recur(f2, truelogic); | ||
| 487 | }); | ||
| 488 | |||
| 489 | if (truelogic == f.get_orlogic()) | ||
| 490 | { | ||
| 491 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 492 | } else { | ||
| 493 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 494 | } | ||
| 495 | } | ||
| 496 | } | ||
| 497 | }; | ||
| 498 | |||
| 499 | cond << recur(_specification_of, _specification_of.get_notlogic()); | ||
| 500 | cond << ")"; | ||
| 501 | conditions.push_back(cond.str()); | ||
| 502 | } | ||
| 503 | |||
| 504 | if (_is_pertainymic) | ||
| 505 | { | ||
| 506 | conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)"); | ||
| 507 | } | ||
| 508 | |||
| 509 | if (!_pertainym_of.empty()) | ||
| 510 | { | ||
| 511 | std::stringstream cond; | ||
| 512 | if (_pertainym_of.get_notlogic()) | ||
| 513 | { | ||
| 514 | cond << "adjective_id NOT IN"; | ||
| 515 | } else { | ||
| 516 | cond << "adjective_id IN"; | ||
| 517 | } | ||
| 518 | |||
| 519 | cond << "(SELECT pertainym_id FROM pertainymy WHERE "; | ||
| 520 | |||
| 521 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 522 | switch (f.get_type()) | ||
| 523 | { | ||
| 524 | case filter<noun>::type::singleton: | ||
| 525 | { | ||
| 526 | if (notlogic == f.get_notlogic()) | ||
| 527 | { | ||
| 528 | return "noun_id = @APERID"; | ||
| 529 | } else { | ||
| 530 | return "noun_id != @APERID"; | ||
| 531 | } | ||
| 532 | } | ||
| 533 | |||
| 534 | case filter<noun>::type::group: | ||
| 535 | { | ||
| 536 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 537 | |||
| 538 | std::list<std::string> clauses; | ||
| 539 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 540 | return recur(f2, truelogic); | ||
| 541 | }); | ||
| 542 | |||
| 543 | if (truelogic == f.get_orlogic()) | ||
| 544 | { | ||
| 545 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 546 | } else { | ||
| 547 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 548 | } | ||
| 549 | } | ||
| 550 | } | ||
| 551 | }; | ||
| 552 | |||
| 553 | cond << recur(_pertainym_of, _pertainym_of.get_notlogic()); | ||
| 554 | cond << ")"; | ||
| 555 | conditions.push_back(cond.str()); | ||
| 556 | } | ||
| 557 | |||
| 558 | if (_is_mannernymic) | ||
| 559 | { | ||
| 560 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)"); | ||
| 561 | } | ||
| 562 | |||
| 563 | if (!_anti_mannernym_of.empty()) | ||
| 564 | { | ||
| 565 | std::stringstream cond; | ||
| 566 | if (_anti_mannernym_of.get_notlogic()) | ||
| 567 | { | ||
| 568 | cond << "adjective_id NOT IN"; | ||
| 569 | } else { | ||
| 570 | cond << "adjective_id IN"; | ||
| 571 | } | ||
| 572 | |||
| 573 | cond << "(SELECT adjective_id FROM mannernymy WHERE "; | ||
| 574 | |||
| 575 | std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string { | ||
| 576 | switch (f.get_type()) | ||
| 577 | { | ||
| 578 | case filter<adverb>::type::singleton: | ||
| 579 | { | ||
| 580 | if (notlogic == f.get_notlogic()) | ||
| 581 | { | ||
| 582 | return "mannernym_id = @MANID"; | ||
| 583 | } else { | ||
| 584 | return "mannernym_id != @MANID"; | ||
| 585 | } | ||
| 586 | } | ||
| 587 | |||
| 588 | case filter<adverb>::type::group: | ||
| 589 | { | ||
| 590 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 591 | |||
| 592 | std::list<std::string> clauses; | ||
| 593 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) { | ||
| 594 | return recur(f2, truelogic); | ||
| 595 | }); | ||
| 596 | |||
| 597 | if (truelogic == f.get_orlogic()) | ||
| 598 | { | ||
| 599 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 600 | } else { | ||
| 601 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 602 | } | ||
| 603 | } | ||
| 604 | } | ||
| 605 | }; | ||
| 606 | |||
| 607 | cond << recur(_anti_mannernym_of, _anti_mannernym_of.get_notlogic()); | ||
| 608 | cond << ")"; | ||
| 609 | conditions.push_back(cond.str()); | ||
| 610 | } | ||
| 611 | /* | ||
| 612 | if (!_derived_from_adjective.empty()) | ||
| 613 | { | ||
| 614 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_2_id = @DERADJ"); | ||
| 615 | std::string cond = "adjective_id IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 616 | conditions.push_back(cond); | ||
| 617 | } | ||
| 618 | |||
| 619 | if (!_not_derived_from_adjective.empty()) | ||
| 620 | { | ||
| 621 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_2_id = @NDERADJ"); | ||
| 622 | 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 ") + ")"; | ||
| 623 | conditions.push_back(cond); | ||
| 624 | } | ||
| 625 | |||
| 626 | if (!_derived_from_adverb.empty()) | ||
| 627 | { | ||
| 628 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); | ||
| 629 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 630 | conditions.push_back(cond); | ||
| 631 | } | ||
| 632 | |||
| 633 | if (!_not_derived_from_adverb.empty()) | ||
| 634 | { | ||
| 635 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); | ||
| 636 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 637 | conditions.push_back(cond); | ||
| 638 | } | ||
| 639 | |||
| 640 | if (!_derived_from_noun.empty()) | ||
| 641 | { | ||
| 642 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN"); | ||
| 643 | std::string cond = "adjective_id IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 644 | conditions.push_back(cond); | ||
| 645 | } | ||
| 646 | |||
| 647 | if (!_not_derived_from_noun.empty()) | ||
| 648 | { | ||
| 649 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); | ||
| 650 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 651 | conditions.push_back(cond); | ||
| 652 | }*/ | ||
| 653 | |||
| 654 | if (!conditions.empty()) | ||
| 655 | { | ||
| 656 | construct << " WHERE "; | ||
| 657 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
| 658 | } | ||
| 659 | |||
| 660 | if (_random) | ||
| 661 | { | ||
| 662 | construct << " ORDER BY RANDOM()"; | ||
| 663 | } | ||
| 664 | |||
| 665 | if (_limit != unlimited) | ||
| 666 | { | ||
| 667 | construct << " LIMIT " << _limit; | ||
| 668 | } | ||
| 669 | |||
| 670 | sqlite3_stmt* ppstmt; | ||
| 671 | std::string query = construct.str(); | ||
| 672 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 673 | { | ||
| 674 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 675 | } | ||
| 676 | |||
| 677 | if (!_rhymes.empty()) | ||
| 678 | { | ||
| 679 | int i = 0; | ||
| 680 | for (auto rhyme : _rhymes) | ||
| 681 | { | ||
| 682 | std::string rhymer = "%" + rhyme; | ||
| 683 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
| 684 | |||
| 685 | i++; | ||
| 686 | } | ||
| 687 | } | ||
| 688 | |||
| 689 | for (auto except : _except) | ||
| 690 | { | ||
| 691 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
| 692 | } | ||
| 693 | |||
| 694 | for (auto attribute : _variant_of.inorder_flatten()) | ||
| 695 | { | ||
| 696 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ATTRID"), attribute._id); | ||
| 697 | } | ||
| 698 | |||
| 699 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
| 700 | { | ||
| 701 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
| 702 | } | ||
| 703 | |||
| 704 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
| 705 | { | ||
| 706 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
| 707 | } | ||
| 708 | |||
| 709 | for (auto specific : _generalization_of.inorder_flatten()) | ||
| 710 | { | ||
| 711 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SPECID"), specific._id); | ||
| 712 | } | ||
| 713 | |||
| 714 | for (auto general : _specification_of.inorder_flatten()) | ||
| 715 | { | ||
| 716 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GENID"), general._id); | ||
| 717 | } | ||
| 718 | |||
| 719 | for (auto n : _pertainym_of.inorder_flatten()) | ||
| 720 | { | ||
| 721 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@APERID"), n._id); | ||
| 722 | } | ||
| 723 | |||
| 724 | for (auto mannernym : _anti_mannernym_of.inorder_flatten()) | ||
| 725 | { | ||
| 726 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MANID"), mannernym._id); | ||
| 727 | } | ||
| 728 | /* | ||
| 729 | for (auto adj : _derived_from_adjective) | ||
| 730 | { | ||
| 731 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
| 732 | } | ||
| 733 | |||
| 734 | for (auto adj : _not_derived_from_adjective) | ||
| 735 | { | ||
| 736 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
| 737 | } | ||
| 738 | |||
| 739 | for (auto adv : _derived_from_adverb) | ||
| 740 | { | ||
| 741 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
| 742 | } | ||
| 743 | |||
| 744 | for (auto adv : _not_derived_from_adverb) | ||
| 745 | { | ||
| 746 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
| 747 | } | ||
| 748 | |||
| 749 | for (auto n : _derived_from_noun) | ||
| 750 | { | ||
| 751 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
| 752 | } | ||
| 753 | |||
| 754 | for (auto n : _not_derived_from_noun) | ||
| 755 | { | ||
| 756 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
| 757 | } | ||
| 758 | */ | ||
| 759 | std::list<adjective> output; | ||
| 760 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 761 | { | ||
| 762 | adjective tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
| 763 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
| 764 | |||
| 765 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
| 766 | { | ||
| 767 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
| 768 | } | ||
| 769 | |||
| 770 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
| 771 | { | ||
| 772 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
| 773 | } | ||
| 774 | |||
| 775 | if (sqlite3_column_type(ppstmt, 4) != SQLITE_NULL) | ||
| 776 | { | ||
| 777 | std::string adjpos(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
| 778 | if (adjpos == "p") | ||
| 779 | { | ||
| 780 | tnc._position = adjective::positioning::predicate; | ||
| 781 | } else if (adjpos == "a") | ||
| 782 | { | ||
| 783 | tnc._position = adjective::positioning::attributive; | ||
| 784 | } else if (adjpos == "i") | ||
| 785 | { | ||
| 786 | tnc._position = adjective::positioning::postnominal; | ||
| 787 | } | ||
| 788 | } | ||
| 789 | |||
| 790 | output.push_back(tnc); | ||
| 791 | } | ||
| 792 | |||
| 793 | sqlite3_finalize(ppstmt); | ||
| 794 | |||
| 795 | for (auto& adjective : output) | ||
| 796 | { | ||
| 797 | query = "SELECT pronunciation FROM adjective_pronunciations WHERE adjective_id = ?"; | ||
| 798 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 799 | { | ||
| 800 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 801 | } | ||
| 802 | |||
| 803 | sqlite3_bind_int(ppstmt, 1, adjective._id); | ||
| 804 | |||
| 805 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 806 | { | ||
| 807 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 808 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
| 809 | |||
| 810 | adjective.pronunciations.push_back(phonemes); | ||
| 811 | } | ||
| 812 | |||
| 813 | sqlite3_finalize(ppstmt); | ||
| 814 | } | ||
| 815 | |||
| 816 | return output; | ||
| 817 | } | ||
| 818 | |||
| 819 | }; | ||
| 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 @@ | |||
| 1 | #ifndef ADJECTIVE_QUERY_H_05E590FD | ||
| 2 | #define ADJECTIVE_QUERY_H_05E590FD | ||
| 3 | |||
| 4 | namespace verbly { | ||
| 5 | |||
| 6 | class adjective_query { | ||
| 7 | public: | ||
| 8 | adjective_query(const data& _data); | ||
| 9 | |||
| 10 | adjective_query& limit(int _limit); | ||
| 11 | adjective_query& random(); | ||
| 12 | adjective_query& except(const adjective& _word); | ||
| 13 | adjective_query& rhymes_with(const word& _word); | ||
| 14 | adjective_query& has_pronunciation(); | ||
| 15 | |||
| 16 | adjective_query& requires_comparative_form(); | ||
| 17 | adjective_query& requires_superlative_form(); | ||
| 18 | adjective_query& position(adjective::positioning pos); | ||
| 19 | |||
| 20 | adjective_query& is_variant(); | ||
| 21 | adjective_query& variant_of(filter<noun> _f); | ||
| 22 | |||
| 23 | adjective_query& has_antonyms(); | ||
| 24 | adjective_query& antonym_of(filter<adjective> _f); | ||
| 25 | |||
| 26 | adjective_query& has_synonyms(); | ||
| 27 | adjective_query& synonym_of(filter<adjective> _f); | ||
| 28 | |||
| 29 | adjective_query& is_generalization(); | ||
| 30 | adjective_query& generalization_of(filter<adjective> _f); | ||
| 31 | |||
| 32 | adjective_query& is_specification(); | ||
| 33 | adjective_query& specification_of(filter<adjective> _f); | ||
| 34 | |||
| 35 | adjective_query& is_pertainymic(); | ||
| 36 | adjective_query& pertainym_of(filter<noun> _f); | ||
| 37 | |||
| 38 | adjective_query& is_mannernymic(); | ||
| 39 | adjective_query& anti_mannernym_of(filter<adverb> _f); | ||
| 40 | |||
| 41 | /* adjective_query& derived_from(const word& _w); | ||
| 42 | adjective_query& not_derived_from(const word& _w);*/ | ||
| 43 | |||
| 44 | std::list<adjective> run() const; | ||
| 45 | |||
| 46 | const static int unlimited = -1; | ||
| 47 | |||
| 48 | protected: | ||
| 49 | const data& _data; | ||
| 50 | int _limit = unlimited; | ||
| 51 | bool _random = false; | ||
| 52 | std::list<std::string> _rhymes; | ||
| 53 | std::list<adjective> _except; | ||
| 54 | bool _has_prn = false; | ||
| 55 | |||
| 56 | bool _requires_comparative_form = false; | ||
| 57 | bool _requires_superlative_form = false; | ||
| 58 | adjective::positioning _position = adjective::positioning::undefined; | ||
| 59 | |||
| 60 | bool _is_variant = false; | ||
| 61 | filter<noun> _variant_of; | ||
| 62 | |||
| 63 | bool _is_antonymic = false; | ||
| 64 | filter<adjective> _antonym_of; | ||
| 65 | |||
| 66 | bool _is_synonymic = false; | ||
| 67 | filter<adjective> _synonym_of; | ||
| 68 | |||
| 69 | bool _is_generalization = false; | ||
| 70 | filter<adjective> _generalization_of; | ||
| 71 | |||
| 72 | bool _is_specification = false; | ||
| 73 | filter<adjective> _specification_of; | ||
| 74 | |||
| 75 | bool _is_pertainymic = false; | ||
| 76 | filter<noun> _pertainym_of; | ||
| 77 | |||
| 78 | bool _is_mannernymic = false; | ||
| 79 | filter<adverb> _anti_mannernym_of; | ||
| 80 | |||
| 81 | /* std::list<adjective> _derived_from_adjective; | ||
| 82 | std::list<adjective> _not_derived_from_adjective; | ||
| 83 | std::list<adverb> _derived_from_adverb; | ||
| 84 | std::list<adverb> _not_derived_from_adverb; | ||
| 85 | std::list<noun> _derived_from_noun; | ||
| 86 | std::list<noun> _not_derived_from_noun;*/ | ||
| 87 | }; | ||
| 88 | |||
| 89 | }; | ||
| 90 | |||
| 91 | #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 @@ | |||
| 2 | 2 | ||
| 3 | namespace verbly { | 3 | namespace verbly { |
| 4 | 4 | ||
| 5 | adverb::adverb() | ||
| 6 | { | ||
| 7 | |||
| 8 | } | ||
| 9 | |||
| 5 | adverb::adverb(const data& _data, int _id) : word(_data, _id) | 10 | adverb::adverb(const data& _data, int _id) : word(_data, _id) |
| 6 | { | 11 | { |
| 7 | 12 | ||
| @@ -9,460 +14,58 @@ namespace verbly { | |||
| 9 | 14 | ||
| 10 | std::string adverb::base_form() const | 15 | std::string adverb::base_form() const |
| 11 | { | 16 | { |
| 17 | assert(_valid == true); | ||
| 18 | |||
| 12 | return _base_form; | 19 | return _base_form; |
| 13 | } | 20 | } |
| 14 | 21 | ||
| 15 | std::string adverb::comparative_form() const | 22 | std::string adverb::comparative_form() const |
| 16 | { | 23 | { |
| 24 | assert(_valid == true); | ||
| 25 | |||
| 17 | return _comparative_form; | 26 | return _comparative_form; |
| 18 | } | 27 | } |
| 19 | 28 | ||
| 20 | std::string adverb::superlative_form() const | 29 | std::string adverb::superlative_form() const |
| 21 | { | 30 | { |
| 31 | assert(_valid == true); | ||
| 32 | |||
| 22 | return _superlative_form; | 33 | return _superlative_form; |
| 23 | } | 34 | } |
| 24 | 35 | ||
| 25 | bool adverb::has_comparative_form() const | 36 | bool adverb::has_comparative_form() const |
| 26 | { | 37 | { |
| 38 | assert(_valid == true); | ||
| 39 | |||
| 27 | return !_comparative_form.empty(); | 40 | return !_comparative_form.empty(); |
| 28 | } | 41 | } |
| 29 | 42 | ||
| 30 | bool adverb::has_superlative_form() const | 43 | bool adverb::has_superlative_form() const |
| 31 | { | 44 | { |
| 45 | assert(_valid == true); | ||
| 46 | |||
| 32 | return !_superlative_form.empty(); | 47 | return !_superlative_form.empty(); |
| 33 | } | 48 | } |
| 34 | 49 | ||
| 35 | adverb_query adverb::antonyms() const | 50 | adverb_query adverb::antonyms() const |
| 36 | { | 51 | { |
| 37 | return _data.adverbs().antonym_of(*this); | 52 | assert(_valid == true); |
| 38 | } | ||
| 39 | |||
| 40 | adverb_query adverb::synonyms() const | ||
| 41 | { | ||
| 42 | return _data.adverbs().synonym_of(*this); | ||
| 43 | } | ||
| 44 | |||
| 45 | adjective_query adverb::anti_mannernyms() const | ||
| 46 | { | ||
| 47 | return _data.adjectives().anti_mannernym_of(*this); | ||
| 48 | } | ||
| 49 | |||
| 50 | adverb_query::adverb_query(const data& _data) : _data(_data) | ||
| 51 | { | ||
| 52 | |||
| 53 | } | ||
| 54 | |||
| 55 | adverb_query& adverb_query::limit(int _limit) | ||
| 56 | { | ||
| 57 | if ((_limit > 0) || (_limit == unlimited)) | ||
| 58 | { | ||
| 59 | this->_limit = _limit; | ||
| 60 | } | ||
| 61 | |||
| 62 | return *this; | ||
| 63 | } | ||
| 64 | |||
| 65 | adverb_query& adverb_query::random(bool _random) | ||
| 66 | { | ||
| 67 | this->_random = _random; | ||
| 68 | |||
| 69 | return *this; | ||
| 70 | } | ||
| 71 | |||
| 72 | adverb_query& adverb_query::except(const adverb& _word) | ||
| 73 | { | ||
| 74 | _except.push_back(_word); | ||
| 75 | 53 | ||
| 76 | return *this; | 54 | return _data->adverbs().antonym_of(*this); |
| 77 | } | 55 | } |
| 78 | 56 | ||
| 79 | adverb_query& adverb_query::rhymes_with(const word& _word) | 57 | adverb_query adverb::synonyms() const |
| 80 | { | ||
| 81 | for (auto rhyme : _word.rhyme_phonemes()) | ||
| 82 | { | ||
| 83 | _rhymes.push_back(rhyme); | ||
| 84 | } | ||
| 85 | |||
| 86 | if (dynamic_cast<const adverb*>(&_word) != nullptr) | ||
| 87 | { | ||
| 88 | _except.push_back(dynamic_cast<const adverb&>(_word)); | ||
| 89 | } | ||
| 90 | |||
| 91 | return *this; | ||
| 92 | } | ||
| 93 | |||
| 94 | adverb_query& adverb_query::has_pronunciation(bool _has_prn) | ||
| 95 | { | ||
| 96 | this->_has_prn = _has_prn; | ||
| 97 | |||
| 98 | return *this; | ||
| 99 | } | ||
| 100 | |||
| 101 | adverb_query& adverb_query::requires_comparative_form(bool _arg) | ||
| 102 | { | ||
| 103 | _requires_comparative_form = _arg; | ||
| 104 | |||
| 105 | return *this; | ||
| 106 | } | ||
| 107 | |||
| 108 | adverb_query& adverb_query::requires_superlative_form(bool _arg) | ||
| 109 | { | ||
| 110 | _requires_superlative_form = _arg; | ||
| 111 | |||
| 112 | return *this; | ||
| 113 | } | ||
| 114 | |||
| 115 | adverb_query& adverb_query::has_antonyms(bool _arg) | ||
| 116 | { | ||
| 117 | _has_antonyms = _arg; | ||
| 118 | |||
| 119 | return *this; | ||
| 120 | } | ||
| 121 | |||
| 122 | adverb_query& adverb_query::antonym_of(const adverb& _adv) | ||
| 123 | { | ||
| 124 | _antonym_of.push_back(_adv); | ||
| 125 | |||
| 126 | return *this; | ||
| 127 | } | ||
| 128 | |||
| 129 | adverb_query& adverb_query::not_antonym_of(const adverb& _adv) | ||
| 130 | { | ||
| 131 | _not_antonym_of.push_back(_adv); | ||
| 132 | |||
| 133 | return *this; | ||
| 134 | } | ||
| 135 | |||
| 136 | adverb_query& adverb_query::has_synonyms(bool _arg) | ||
| 137 | { | ||
| 138 | _has_synonyms = _arg; | ||
| 139 | |||
| 140 | return *this; | ||
| 141 | } | ||
| 142 | |||
| 143 | adverb_query& adverb_query::synonym_of(const adverb& _adv) | ||
| 144 | { | ||
| 145 | _synonym_of.push_back(_adv); | ||
| 146 | |||
| 147 | return *this; | ||
| 148 | } | ||
| 149 | |||
| 150 | adverb_query& adverb_query::not_synonym_of(const adverb& _adv) | ||
| 151 | { | ||
| 152 | _not_synonym_of.push_back(_adv); | ||
| 153 | |||
| 154 | return *this; | ||
| 155 | } | ||
| 156 | |||
| 157 | adverb_query& adverb_query::is_mannernymic(bool _arg) | ||
| 158 | { | ||
| 159 | _is_mannernymic = _arg; | ||
| 160 | |||
| 161 | return *this; | ||
| 162 | } | ||
| 163 | |||
| 164 | adverb_query& adverb_query::mannernym_of(const adjective& _adj) | ||
| 165 | { | ||
| 166 | _mannernym_of.push_back(_adj); | ||
| 167 | |||
| 168 | return *this; | ||
| 169 | } | ||
| 170 | |||
| 171 | adverb_query& adverb_query::derived_from(const word& _w) | ||
| 172 | { | ||
| 173 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
| 174 | { | ||
| 175 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 176 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 177 | { | ||
| 178 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 179 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 180 | { | ||
| 181 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 182 | } | ||
| 183 | |||
| 184 | return *this; | ||
| 185 | } | ||
| 186 | |||
| 187 | adverb_query& adverb_query::not_derived_from(const word& _w) | ||
| 188 | { | 58 | { |
| 189 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 59 | assert(_valid == true); |
| 190 | { | ||
| 191 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 192 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 193 | { | ||
| 194 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 195 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 196 | { | ||
| 197 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 198 | } | ||
| 199 | 60 | ||
| 200 | return *this; | 61 | return _data->adverbs().synonym_of(*this); |
| 201 | } | 62 | } |
| 202 | 63 | ||
| 203 | std::list<adverb> adverb_query::run() const | 64 | adjective_query adverb::anti_mannernyms() const |
| 204 | { | 65 | { |
| 205 | std::stringstream construct; | 66 | assert(_valid == true); |
| 206 | construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; | ||
| 207 | std::list<std::string> conditions; | ||
| 208 | |||
| 209 | if (_has_prn) | ||
| 210 | { | ||
| 211 | conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)"); | ||
| 212 | } | ||
| 213 | |||
| 214 | if (!_rhymes.empty()) | ||
| 215 | { | ||
| 216 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
| 217 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 218 | conditions.push_back(cond); | ||
| 219 | } | ||
| 220 | |||
| 221 | for (auto except : _except) | ||
| 222 | { | ||
| 223 | conditions.push_back("adverb_id != @EXCID"); | ||
| 224 | } | ||
| 225 | |||
| 226 | if (_requires_comparative_form) | ||
| 227 | { | ||
| 228 | conditions.push_back("comparative IS NOT NULL"); | ||
| 229 | } | ||
| 230 | |||
| 231 | if (_requires_superlative_form) | ||
| 232 | { | ||
| 233 | conditions.push_back("superlative IS NOT NULL"); | ||
| 234 | } | ||
| 235 | |||
| 236 | if (_has_antonyms) | ||
| 237 | { | ||
| 238 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)"); | ||
| 239 | } | ||
| 240 | |||
| 241 | if (!_antonym_of.empty()) | ||
| 242 | { | ||
| 243 | std::list<std::string> clauses(_antonym_of.size(), "adverb_1_id = @ANTID"); | ||
| 244 | std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 245 | conditions.push_back(cond); | ||
| 246 | } | ||
| 247 | |||
| 248 | if (!_not_antonym_of.empty()) | ||
| 249 | { | ||
| 250 | std::list<std::string> clauses(_not_antonym_of.size(), "adverb_1_id = @NANTID"); | ||
| 251 | std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 252 | conditions.push_back(cond); | ||
| 253 | } | ||
| 254 | |||
| 255 | if (_has_synonyms) | ||
| 256 | { | ||
| 257 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)"); | ||
| 258 | } | ||
| 259 | 67 | ||
| 260 | if (!_synonym_of.empty()) | 68 | return _data->adjectives().anti_mannernym_of(*this); |
| 261 | { | ||
| 262 | std::list<std::string> clauses(_synonym_of.size(), "adverb_1_id = @SYNID"); | ||
| 263 | std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 264 | conditions.push_back(cond); | ||
| 265 | } | ||
| 266 | |||
| 267 | if (!_not_synonym_of.empty()) | ||
| 268 | { | ||
| 269 | std::list<std::string> clauses(_not_synonym_of.size(), "adverb_1_id = @NSYNID"); | ||
| 270 | std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 271 | conditions.push_back(cond); | ||
| 272 | } | ||
| 273 | |||
| 274 | if (_is_mannernymic) | ||
| 275 | { | ||
| 276 | conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)"); | ||
| 277 | } | ||
| 278 | |||
| 279 | if (!_mannernym_of.empty()) | ||
| 280 | { | ||
| 281 | std::list<std::string> clauses(_mannernym_of.size(), "adjective_id = @AMANID"); | ||
| 282 | std::string cond = "adverb_id IN (SELECT mannernym_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 283 | conditions.push_back(cond); | ||
| 284 | } | ||
| 285 | |||
| 286 | if (!_derived_from_adjective.empty()) | ||
| 287 | { | ||
| 288 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); | ||
| 289 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 290 | conditions.push_back(cond); | ||
| 291 | } | ||
| 292 | |||
| 293 | if (!_not_derived_from_adjective.empty()) | ||
| 294 | { | ||
| 295 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); | ||
| 296 | std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 297 | conditions.push_back(cond); | ||
| 298 | } | ||
| 299 | |||
| 300 | if (!_derived_from_adverb.empty()) | ||
| 301 | { | ||
| 302 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_2_id = @DERADV"); | ||
| 303 | std::string cond = "adverb_id IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 304 | conditions.push_back(cond); | ||
| 305 | } | ||
| 306 | |||
| 307 | if (!_not_derived_from_adverb.empty()) | ||
| 308 | { | ||
| 309 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_2_id = @NDERADV"); | ||
| 310 | 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 ") + ")"; | ||
| 311 | conditions.push_back(cond); | ||
| 312 | } | ||
| 313 | |||
| 314 | if (!_derived_from_noun.empty()) | ||
| 315 | { | ||
| 316 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN"); | ||
| 317 | std::string cond = "adverb_id IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 318 | conditions.push_back(cond); | ||
| 319 | } | ||
| 320 | |||
| 321 | if (!_not_derived_from_noun.empty()) | ||
| 322 | { | ||
| 323 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); | ||
| 324 | std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 325 | conditions.push_back(cond); | ||
| 326 | } | ||
| 327 | |||
| 328 | if (!conditions.empty()) | ||
| 329 | { | ||
| 330 | construct << " WHERE "; | ||
| 331 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
| 332 | } | ||
| 333 | |||
| 334 | if (_random) | ||
| 335 | { | ||
| 336 | construct << " ORDER BY RANDOM()"; | ||
| 337 | } | ||
| 338 | |||
| 339 | if (_limit != unlimited) | ||
| 340 | { | ||
| 341 | construct << " LIMIT " << _limit; | ||
| 342 | } | ||
| 343 | |||
| 344 | sqlite3_stmt* ppstmt; | ||
| 345 | std::string query = construct.str(); | ||
| 346 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 347 | { | ||
| 348 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 349 | } | ||
| 350 | |||
| 351 | if (!_rhymes.empty()) | ||
| 352 | { | ||
| 353 | int i = 0; | ||
| 354 | for (auto rhyme : _rhymes) | ||
| 355 | { | ||
| 356 | std::string rhymer = "%" + rhyme; | ||
| 357 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
| 358 | |||
| 359 | i++; | ||
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | for (auto except : _except) | ||
| 364 | { | ||
| 365 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
| 366 | } | ||
| 367 | |||
| 368 | for (auto antonym : _antonym_of) | ||
| 369 | { | ||
| 370 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
| 371 | } | ||
| 372 | |||
| 373 | for (auto antonym : _not_antonym_of) | ||
| 374 | { | ||
| 375 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
| 376 | } | ||
| 377 | |||
| 378 | for (auto synonym : _synonym_of) | ||
| 379 | { | ||
| 380 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
| 381 | } | ||
| 382 | |||
| 383 | for (auto synonym : _not_synonym_of) | ||
| 384 | { | ||
| 385 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
| 386 | } | ||
| 387 | |||
| 388 | for (auto adj : _mannernym_of) | ||
| 389 | { | ||
| 390 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@AMANID"), adj._id); | ||
| 391 | } | ||
| 392 | |||
| 393 | for (auto adj : _derived_from_adjective) | ||
| 394 | { | ||
| 395 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
| 396 | } | ||
| 397 | |||
| 398 | for (auto adj : _not_derived_from_adjective) | ||
| 399 | { | ||
| 400 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
| 401 | } | ||
| 402 | |||
| 403 | for (auto adv : _derived_from_adverb) | ||
| 404 | { | ||
| 405 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
| 406 | } | ||
| 407 | |||
| 408 | for (auto adv : _not_derived_from_adverb) | ||
| 409 | { | ||
| 410 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
| 411 | } | ||
| 412 | |||
| 413 | for (auto n : _derived_from_noun) | ||
| 414 | { | ||
| 415 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
| 416 | } | ||
| 417 | |||
| 418 | for (auto n : _not_derived_from_noun) | ||
| 419 | { | ||
| 420 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
| 421 | } | ||
| 422 | |||
| 423 | std::list<adverb> output; | ||
| 424 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 425 | { | ||
| 426 | adverb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
| 427 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
| 428 | |||
| 429 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
| 430 | { | ||
| 431 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
| 432 | } | ||
| 433 | |||
| 434 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
| 435 | { | ||
| 436 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
| 437 | } | ||
| 438 | |||
| 439 | output.push_back(tnc); | ||
| 440 | } | ||
| 441 | |||
| 442 | sqlite3_finalize(ppstmt); | ||
| 443 | |||
| 444 | for (auto& adverb : output) | ||
| 445 | { | ||
| 446 | query = "SELECT pronunciation FROM adverb_pronunciations WHERE adverb_id = ?"; | ||
| 447 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 448 | { | ||
| 449 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 450 | } | ||
| 451 | |||
| 452 | sqlite3_bind_int(ppstmt, 1, adverb._id); | ||
| 453 | |||
| 454 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 455 | { | ||
| 456 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 457 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
| 458 | |||
| 459 | adverb.pronunciations.push_back(phonemes); | ||
| 460 | } | ||
| 461 | |||
| 462 | sqlite3_finalize(ppstmt); | ||
| 463 | } | ||
| 464 | |||
| 465 | return output; | ||
| 466 | } | 69 | } |
| 467 | 70 | ||
| 468 | }; | 71 | }; |
| 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 { | |||
| 12 | friend class adverb_query; | 12 | friend class adverb_query; |
| 13 | 13 | ||
| 14 | public: | 14 | public: |
| 15 | adverb(); | ||
| 15 | adverb(const data& _data, int _id); | 16 | adverb(const data& _data, int _id); |
| 16 | 17 | ||
| 17 | std::string base_form() const; | 18 | std::string base_form() const; |
| @@ -29,67 +30,6 @@ namespace verbly { | |||
| 29 | adverb_query& not_derived_from(const word& _w); | 30 | adverb_query& not_derived_from(const word& _w); |
| 30 | }; | 31 | }; |
| 31 | 32 | ||
| 32 | class adverb_query { | ||
| 33 | public: | ||
| 34 | adverb_query(const data& _data); | ||
| 35 | |||
| 36 | adverb_query& limit(int _limit); | ||
| 37 | adverb_query& random(bool _random); | ||
| 38 | adverb_query& except(const adverb& _word); | ||
| 39 | adverb_query& rhymes_with(const word& _word); | ||
| 40 | adverb_query& has_pronunciation(bool _has_prn); | ||
| 41 | |||
| 42 | adverb_query& requires_comparative_form(bool _arg); | ||
| 43 | adverb_query& requires_superlative_form(bool _arg); | ||
| 44 | |||
| 45 | adverb_query& has_antonyms(bool _arg); | ||
| 46 | adverb_query& antonym_of(const adverb& _adv); | ||
| 47 | adverb_query& not_antonym_of(const adverb& _adv); | ||
| 48 | |||
| 49 | adverb_query& has_synonyms(bool _arg); | ||
| 50 | adverb_query& synonym_of(const adverb& _adv); | ||
| 51 | adverb_query& not_synonym_of(const adverb& _adv); | ||
| 52 | |||
| 53 | adverb_query& is_mannernymic(bool _arg); | ||
| 54 | adverb_query& mannernym_of(const adjective& _adj); | ||
| 55 | |||
| 56 | adverb_query& derived_from(const word& _w); | ||
| 57 | adverb_query& not_derived_from(const word& _w); | ||
| 58 | |||
| 59 | std::list<adverb> run() const; | ||
| 60 | |||
| 61 | const static int unlimited = -1; | ||
| 62 | |||
| 63 | private: | ||
| 64 | const data& _data; | ||
| 65 | int _limit = unlimited; | ||
| 66 | bool _random = false; | ||
| 67 | std::list<std::string> _rhymes; | ||
| 68 | std::list<adverb> _except; | ||
| 69 | bool _has_prn = false; | ||
| 70 | |||
| 71 | bool _requires_comparative_form = false; | ||
| 72 | bool _requires_superlative_form = false; | ||
| 73 | |||
| 74 | bool _has_antonyms = false; | ||
| 75 | std::list<adverb> _antonym_of; | ||
| 76 | std::list<adverb> _not_antonym_of; | ||
| 77 | |||
| 78 | bool _has_synonyms = false; | ||
| 79 | std::list<adverb> _synonym_of; | ||
| 80 | std::list<adverb> _not_synonym_of; | ||
| 81 | |||
| 82 | bool _is_mannernymic = false; | ||
| 83 | std::list<adjective> _mannernym_of; | ||
| 84 | |||
| 85 | std::list<adjective> _derived_from_adjective; | ||
| 86 | std::list<adjective> _not_derived_from_adjective; | ||
| 87 | std::list<adverb> _derived_from_adverb; | ||
| 88 | std::list<adverb> _not_derived_from_adverb; | ||
| 89 | std::list<noun> _derived_from_noun; | ||
| 90 | std::list<noun> _not_derived_from_noun; | ||
| 91 | }; | ||
| 92 | |||
| 93 | }; | 33 | }; |
| 94 | 34 | ||
| 95 | #endif /* end of include guard: ADVERB_H_86F8302F */ | 35 | #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 @@ | |||
| 1 | #include "verbly.h" | ||
| 2 | |||
| 3 | namespace verbly { | ||
| 4 | |||
| 5 | adverb_query::adverb_query(const data& _data) : _data(_data) | ||
| 6 | { | ||
| 7 | |||
| 8 | } | ||
| 9 | |||
| 10 | adverb_query& adverb_query::limit(int _limit) | ||
| 11 | { | ||
| 12 | if ((_limit > 0) || (_limit == unlimited)) | ||
| 13 | { | ||
| 14 | this->_limit = _limit; | ||
| 15 | } | ||
| 16 | |||
| 17 | return *this; | ||
| 18 | } | ||
| 19 | |||
| 20 | adverb_query& adverb_query::random() | ||
| 21 | { | ||
| 22 | this->_random = true; | ||
| 23 | |||
| 24 | return *this; | ||
| 25 | } | ||
| 26 | |||
| 27 | adverb_query& adverb_query::except(const adverb& _word) | ||
| 28 | { | ||
| 29 | _except.push_back(_word); | ||
| 30 | |||
| 31 | return *this; | ||
| 32 | } | ||
| 33 | |||
| 34 | adverb_query& adverb_query::rhymes_with(const word& _word) | ||
| 35 | { | ||
| 36 | for (auto rhyme : _word.rhyme_phonemes()) | ||
| 37 | { | ||
| 38 | _rhymes.push_back(rhyme); | ||
| 39 | } | ||
| 40 | |||
| 41 | if (dynamic_cast<const adverb*>(&_word) != nullptr) | ||
| 42 | { | ||
| 43 | _except.push_back(dynamic_cast<const adverb&>(_word)); | ||
| 44 | } | ||
| 45 | |||
| 46 | return *this; | ||
| 47 | } | ||
| 48 | |||
| 49 | adverb_query& adverb_query::has_pronunciation() | ||
| 50 | { | ||
| 51 | this->_has_prn = true; | ||
| 52 | |||
| 53 | return *this; | ||
| 54 | } | ||
| 55 | |||
| 56 | adverb_query& adverb_query::requires_comparative_form() | ||
| 57 | { | ||
| 58 | _requires_comparative_form = true; | ||
| 59 | |||
| 60 | return *this; | ||
| 61 | } | ||
| 62 | |||
| 63 | adverb_query& adverb_query::requires_superlative_form() | ||
| 64 | { | ||
| 65 | _requires_superlative_form = true; | ||
| 66 | |||
| 67 | return *this; | ||
| 68 | } | ||
| 69 | |||
| 70 | adverb_query& adverb_query::has_antonyms() | ||
| 71 | { | ||
| 72 | _has_antonyms = true; | ||
| 73 | |||
| 74 | return *this; | ||
| 75 | } | ||
| 76 | |||
| 77 | adverb_query& adverb_query::antonym_of(filter<adverb> _f) | ||
| 78 | { | ||
| 79 | _f.clean(); | ||
| 80 | _antonym_of = _f; | ||
| 81 | |||
| 82 | return *this; | ||
| 83 | } | ||
| 84 | |||
| 85 | adverb_query& adverb_query::has_synonyms() | ||
| 86 | { | ||
| 87 | _has_synonyms = true; | ||
| 88 | |||
| 89 | return *this; | ||
| 90 | } | ||
| 91 | |||
| 92 | adverb_query& adverb_query::synonym_of(filter<adverb> _f) | ||
| 93 | { | ||
| 94 | _f.clean(); | ||
| 95 | _synonym_of = _f; | ||
| 96 | |||
| 97 | return *this; | ||
| 98 | } | ||
| 99 | |||
| 100 | adverb_query& adverb_query::is_mannernymic() | ||
| 101 | { | ||
| 102 | _is_mannernymic = true; | ||
| 103 | |||
| 104 | return *this; | ||
| 105 | } | ||
| 106 | |||
| 107 | adverb_query& adverb_query::mannernym_of(filter<adjective> _f) | ||
| 108 | { | ||
| 109 | _f.clean(); | ||
| 110 | _mannernym_of = _f; | ||
| 111 | |||
| 112 | return *this; | ||
| 113 | } | ||
| 114 | /* | ||
| 115 | adverb_query& adverb_query::derived_from(const word& _w) | ||
| 116 | { | ||
| 117 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
| 118 | { | ||
| 119 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 120 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 121 | { | ||
| 122 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 123 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 124 | { | ||
| 125 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 126 | } | ||
| 127 | |||
| 128 | return *this; | ||
| 129 | } | ||
| 130 | |||
| 131 | adverb_query& adverb_query::not_derived_from(const word& _w) | ||
| 132 | { | ||
| 133 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
| 134 | { | ||
| 135 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 136 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 137 | { | ||
| 138 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 139 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 140 | { | ||
| 141 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 142 | } | ||
| 143 | |||
| 144 | return *this; | ||
| 145 | } | ||
| 146 | */ | ||
| 147 | std::list<adverb> adverb_query::run() const | ||
| 148 | { | ||
| 149 | std::stringstream construct; | ||
| 150 | construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; | ||
| 151 | std::list<std::string> conditions; | ||
| 152 | |||
| 153 | if (_has_prn) | ||
| 154 | { | ||
| 155 | conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)"); | ||
| 156 | } | ||
| 157 | |||
| 158 | if (!_rhymes.empty()) | ||
| 159 | { | ||
| 160 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
| 161 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 162 | conditions.push_back(cond); | ||
| 163 | } | ||
| 164 | |||
| 165 | for (auto except : _except) | ||
| 166 | { | ||
| 167 | conditions.push_back("adverb_id != @EXCID"); | ||
| 168 | } | ||
| 169 | |||
| 170 | if (_requires_comparative_form) | ||
| 171 | { | ||
| 172 | conditions.push_back("comparative IS NOT NULL"); | ||
| 173 | } | ||
| 174 | |||
| 175 | if (_requires_superlative_form) | ||
| 176 | { | ||
| 177 | conditions.push_back("superlative IS NOT NULL"); | ||
| 178 | } | ||
| 179 | |||
| 180 | if (_has_antonyms) | ||
| 181 | { | ||
| 182 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)"); | ||
| 183 | } | ||
| 184 | |||
| 185 | if (!_antonym_of.empty()) | ||
| 186 | { | ||
| 187 | std::stringstream cond; | ||
| 188 | if (_antonym_of.get_notlogic()) | ||
| 189 | { | ||
| 190 | cond << "adverb_id NOT IN"; | ||
| 191 | } else { | ||
| 192 | cond << "adverb_id IN"; | ||
| 193 | } | ||
| 194 | |||
| 195 | cond << "(SELECT adverb_2_id FROM adverb_antonymy WHERE "; | ||
| 196 | |||
| 197 | std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string { | ||
| 198 | switch (f.get_type()) | ||
| 199 | { | ||
| 200 | case filter<adverb>::type::singleton: | ||
| 201 | { | ||
| 202 | if (notlogic == f.get_notlogic()) | ||
| 203 | { | ||
| 204 | return "adverb_1_id = @ANTID"; | ||
| 205 | } else { | ||
| 206 | return "adverb_1_id != @ANTID"; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | case filter<adverb>::type::group: | ||
| 211 | { | ||
| 212 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 213 | |||
| 214 | std::list<std::string> clauses; | ||
| 215 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) { | ||
| 216 | return recur(f2, truelogic); | ||
| 217 | }); | ||
| 218 | |||
| 219 | if (truelogic == f.get_orlogic()) | ||
| 220 | { | ||
| 221 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 222 | } else { | ||
| 223 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | } | ||
| 227 | }; | ||
| 228 | |||
| 229 | cond << recur(_antonym_of, _antonym_of.get_notlogic()); | ||
| 230 | cond << ")"; | ||
| 231 | conditions.push_back(cond.str()); | ||
| 232 | } | ||
| 233 | |||
| 234 | if (_has_synonyms) | ||
| 235 | { | ||
| 236 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)"); | ||
| 237 | } | ||
| 238 | |||
| 239 | if (!_synonym_of.empty()) | ||
| 240 | { | ||
| 241 | std::stringstream cond; | ||
| 242 | if (_antonym_of.get_notlogic()) | ||
| 243 | { | ||
| 244 | cond << "adverb_id NOT IN"; | ||
| 245 | } else { | ||
| 246 | cond << "adverb_id IN"; | ||
| 247 | } | ||
| 248 | |||
| 249 | cond << "(SELECT adverb_2_id FROM adverb_synonymy WHERE "; | ||
| 250 | |||
| 251 | std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string { | ||
| 252 | switch (f.get_type()) | ||
| 253 | { | ||
| 254 | case filter<adverb>::type::singleton: | ||
| 255 | { | ||
| 256 | if (notlogic == f.get_notlogic()) | ||
| 257 | { | ||
| 258 | return "adverb_1_id = @SYNID"; | ||
| 259 | } else { | ||
| 260 | return "adverb_1_id != @SYNID"; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | case filter<adverb>::type::group: | ||
| 265 | { | ||
| 266 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 267 | |||
| 268 | std::list<std::string> clauses; | ||
| 269 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) { | ||
| 270 | return recur(f2, truelogic); | ||
| 271 | }); | ||
| 272 | |||
| 273 | if (truelogic == f.get_orlogic()) | ||
| 274 | { | ||
| 275 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 276 | } else { | ||
| 277 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 278 | } | ||
| 279 | } | ||
| 280 | } | ||
| 281 | }; | ||
| 282 | |||
| 283 | cond << recur(_synonym_of, _synonym_of.get_notlogic()); | ||
| 284 | cond << ")"; | ||
| 285 | conditions.push_back(cond.str()); | ||
| 286 | } | ||
| 287 | |||
| 288 | if (_is_mannernymic) | ||
| 289 | { | ||
| 290 | conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)"); | ||
| 291 | } | ||
| 292 | |||
| 293 | if (!_mannernym_of.empty()) | ||
| 294 | { | ||
| 295 | std::stringstream cond; | ||
| 296 | if (_antonym_of.get_notlogic()) | ||
| 297 | { | ||
| 298 | cond << "adverb_id NOT IN"; | ||
| 299 | } else { | ||
| 300 | cond << "adverb_id IN"; | ||
| 301 | } | ||
| 302 | |||
| 303 | cond << "(SELECT mannernym_id FROM mannernymy WHERE "; | ||
| 304 | |||
| 305 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
| 306 | switch (f.get_type()) | ||
| 307 | { | ||
| 308 | case filter<adjective>::type::singleton: | ||
| 309 | { | ||
| 310 | if (notlogic == f.get_notlogic()) | ||
| 311 | { | ||
| 312 | return "adjective_id = @AMANID"; | ||
| 313 | } else { | ||
| 314 | return "adjective_id != @AMANID"; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | case filter<adjective>::type::group: | ||
| 319 | { | ||
| 320 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 321 | |||
| 322 | std::list<std::string> clauses; | ||
| 323 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
| 324 | return recur(f2, truelogic); | ||
| 325 | }); | ||
| 326 | |||
| 327 | if (truelogic == f.get_orlogic()) | ||
| 328 | { | ||
| 329 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 330 | } else { | ||
| 331 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 332 | } | ||
| 333 | } | ||
| 334 | } | ||
| 335 | }; | ||
| 336 | |||
| 337 | cond << recur(_mannernym_of, _mannernym_of.get_notlogic()); | ||
| 338 | cond << ")"; | ||
| 339 | conditions.push_back(cond.str()); | ||
| 340 | } | ||
| 341 | |||
| 342 | /* if (!_derived_from_adjective.empty()) | ||
| 343 | { | ||
| 344 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); | ||
| 345 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 346 | conditions.push_back(cond); | ||
| 347 | } | ||
| 348 | |||
| 349 | if (!_not_derived_from_adjective.empty()) | ||
| 350 | { | ||
| 351 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); | ||
| 352 | std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 353 | conditions.push_back(cond); | ||
| 354 | } | ||
| 355 | |||
| 356 | if (!_derived_from_adverb.empty()) | ||
| 357 | { | ||
| 358 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_2_id = @DERADV"); | ||
| 359 | std::string cond = "adverb_id IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 360 | conditions.push_back(cond); | ||
| 361 | } | ||
| 362 | |||
| 363 | if (!_not_derived_from_adverb.empty()) | ||
| 364 | { | ||
| 365 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_2_id = @NDERADV"); | ||
| 366 | 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 ") + ")"; | ||
| 367 | conditions.push_back(cond); | ||
| 368 | } | ||
| 369 | |||
| 370 | if (!_derived_from_noun.empty()) | ||
| 371 | { | ||
| 372 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN"); | ||
| 373 | std::string cond = "adverb_id IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 374 | conditions.push_back(cond); | ||
| 375 | } | ||
| 376 | |||
| 377 | if (!_not_derived_from_noun.empty()) | ||
| 378 | { | ||
| 379 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); | ||
| 380 | std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 381 | conditions.push_back(cond); | ||
| 382 | }*/ | ||
| 383 | |||
| 384 | if (!conditions.empty()) | ||
| 385 | { | ||
| 386 | construct << " WHERE "; | ||
| 387 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
| 388 | } | ||
| 389 | |||
| 390 | if (_random) | ||
| 391 | { | ||
| 392 | construct << " ORDER BY RANDOM()"; | ||
| 393 | } | ||
| 394 | |||
| 395 | if (_limit != unlimited) | ||
| 396 | { | ||
| 397 | construct << " LIMIT " << _limit; | ||
| 398 | } | ||
| 399 | |||
| 400 | sqlite3_stmt* ppstmt; | ||
| 401 | std::string query = construct.str(); | ||
| 402 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 403 | { | ||
| 404 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 405 | } | ||
| 406 | |||
| 407 | if (!_rhymes.empty()) | ||
| 408 | { | ||
| 409 | int i = 0; | ||
| 410 | for (auto rhyme : _rhymes) | ||
| 411 | { | ||
| 412 | std::string rhymer = "%" + rhyme; | ||
| 413 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
| 414 | |||
| 415 | i++; | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | for (auto except : _except) | ||
| 420 | { | ||
| 421 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
| 422 | } | ||
| 423 | |||
| 424 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
| 425 | { | ||
| 426 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
| 427 | } | ||
| 428 | |||
| 429 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
| 430 | { | ||
| 431 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
| 432 | } | ||
| 433 | |||
| 434 | for (auto adj : _mannernym_of.inorder_flatten()) | ||
| 435 | { | ||
| 436 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@AMANID"), adj._id); | ||
| 437 | } | ||
| 438 | /* | ||
| 439 | for (auto adj : _derived_from_adjective) | ||
| 440 | { | ||
| 441 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
| 442 | } | ||
| 443 | |||
| 444 | for (auto adj : _not_derived_from_adjective) | ||
| 445 | { | ||
| 446 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
| 447 | } | ||
| 448 | |||
| 449 | for (auto adv : _derived_from_adverb) | ||
| 450 | { | ||
| 451 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
| 452 | } | ||
| 453 | |||
| 454 | for (auto adv : _not_derived_from_adverb) | ||
| 455 | { | ||
| 456 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
| 457 | } | ||
| 458 | |||
| 459 | for (auto n : _derived_from_noun) | ||
| 460 | { | ||
| 461 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
| 462 | } | ||
| 463 | |||
| 464 | for (auto n : _not_derived_from_noun) | ||
| 465 | { | ||
| 466 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
| 467 | }*/ | ||
| 468 | |||
| 469 | std::list<adverb> output; | ||
| 470 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 471 | { | ||
| 472 | adverb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
| 473 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
| 474 | |||
| 475 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
| 476 | { | ||
| 477 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
| 478 | } | ||
| 479 | |||
| 480 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
| 481 | { | ||
| 482 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
| 483 | } | ||
| 484 | |||
| 485 | output.push_back(tnc); | ||
| 486 | } | ||
| 487 | |||
| 488 | sqlite3_finalize(ppstmt); | ||
| 489 | |||
| 490 | for (auto& adverb : output) | ||
| 491 | { | ||
| 492 | query = "SELECT pronunciation FROM adverb_pronunciations WHERE adverb_id = ?"; | ||
| 493 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 494 | { | ||
| 495 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 496 | } | ||
| 497 | |||
| 498 | sqlite3_bind_int(ppstmt, 1, adverb._id); | ||
| 499 | |||
| 500 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 501 | { | ||
| 502 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 503 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
| 504 | |||
| 505 | adverb.pronunciations.push_back(phonemes); | ||
| 506 | } | ||
| 507 | |||
| 508 | sqlite3_finalize(ppstmt); | ||
| 509 | } | ||
| 510 | |||
| 511 | return output; | ||
| 512 | } | ||
| 513 | |||
| 514 | }; | ||
| 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 @@ | |||
| 1 | #ifndef ADVERB_QUERY_H_CA13CCDD | ||
| 2 | #define ADVERB_QUERY_H_CA13CCDD | ||
| 3 | |||
| 4 | namespace verbly { | ||
| 5 | |||
| 6 | class adverb_query { | ||
| 7 | public: | ||
| 8 | adverb_query(const data& _data); | ||
| 9 | |||
| 10 | adverb_query& limit(int _limit); | ||
| 11 | adverb_query& random(); | ||
| 12 | adverb_query& except(const adverb& _word); | ||
| 13 | adverb_query& rhymes_with(const word& _word); | ||
| 14 | adverb_query& has_pronunciation(); | ||
| 15 | |||
| 16 | adverb_query& requires_comparative_form(); | ||
| 17 | adverb_query& requires_superlative_form(); | ||
| 18 | |||
| 19 | adverb_query& has_antonyms(); | ||
| 20 | adverb_query& antonym_of(filter<adverb> _f); | ||
| 21 | |||
| 22 | adverb_query& has_synonyms(); | ||
| 23 | adverb_query& synonym_of(filter<adverb> _f); | ||
| 24 | |||
| 25 | adverb_query& is_mannernymic(); | ||
| 26 | adverb_query& mannernym_of(filter<adjective> _f); | ||
| 27 | |||
| 28 | /* adverb_query& derived_from(const word& _w); | ||
| 29 | adverb_query& not_derived_from(const word& _w);*/ | ||
| 30 | |||
| 31 | std::list<adverb> run() const; | ||
| 32 | |||
| 33 | const static int unlimited = -1; | ||
| 34 | |||
| 35 | private: | ||
| 36 | const data& _data; | ||
| 37 | int _limit = unlimited; | ||
| 38 | bool _random = false; | ||
| 39 | std::list<std::string> _rhymes; | ||
| 40 | std::list<adverb> _except; | ||
| 41 | bool _has_prn = false; | ||
| 42 | |||
| 43 | bool _requires_comparative_form = false; | ||
| 44 | bool _requires_superlative_form = false; | ||
| 45 | |||
| 46 | bool _has_antonyms = false; | ||
| 47 | filter<adverb> _antonym_of; | ||
| 48 | |||
| 49 | bool _has_synonyms = false; | ||
| 50 | filter<adverb> _synonym_of; | ||
| 51 | |||
| 52 | bool _is_mannernymic = false; | ||
| 53 | filter<adjective> _mannernym_of; | ||
| 54 | |||
| 55 | /* std::list<adjective> _derived_from_adjective; | ||
| 56 | std::list<adjective> _not_derived_from_adjective; | ||
| 57 | std::list<adverb> _derived_from_adverb; | ||
| 58 | std::list<adverb> _not_derived_from_adverb; | ||
| 59 | std::list<noun> _derived_from_noun; | ||
| 60 | std::list<noun> _not_derived_from_noun;*/ | ||
| 61 | }; | ||
| 62 | |||
| 63 | }; | ||
| 64 | |||
| 65 | #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 @@ | |||
| 1 | #include <cstddef> | ||
| 2 | #include <memory> | ||
| 3 | #include <type_traits> | ||
| 4 | #include <utility> | ||
| 5 | |||
| 6 | namespace std { | ||
| 7 | template<class T> struct _Unique_if { | ||
| 8 | typedef unique_ptr<T> _Single_object; | ||
| 9 | }; | ||
| 10 | |||
| 11 | template<class T> struct _Unique_if<T[]> { | ||
| 12 | typedef unique_ptr<T[]> _Unknown_bound; | ||
| 13 | }; | ||
| 14 | |||
| 15 | template<class T, size_t N> struct _Unique_if<T[N]> { | ||
| 16 | typedef void _Known_bound; | ||
| 17 | }; | ||
| 18 | |||
| 19 | template<class T, class... Args> | ||
| 20 | typename _Unique_if<T>::_Single_object | ||
| 21 | make_unique(Args&&... args) { | ||
| 22 | return unique_ptr<T>(new T(std::forward<Args>(args)...)); | ||
| 23 | } | ||
| 24 | |||
| 25 | template<class T> | ||
| 26 | typename _Unique_if<T>::_Unknown_bound | ||
| 27 | make_unique(size_t n) { | ||
| 28 | typedef typename remove_extent<T>::type U; | ||
| 29 | return unique_ptr<T>(new U[n]()); | ||
| 30 | } | ||
| 31 | |||
| 32 | template<class T, class... Args> | ||
| 33 | typename _Unique_if<T>::_Known_bound | ||
| 34 | make_unique(Args&&...) = delete; | ||
| 35 | } | ||
| 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 { | |||
| 46 | { | 46 | { |
| 47 | return noun_query(*this); | 47 | return noun_query(*this); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | frame_query data::frames() const | ||
| 51 | { | ||
| 52 | return frame_query(*this); | ||
| 53 | } | ||
| 54 | |||
| 55 | preposition_query data::prepositions() const | ||
| 56 | { | ||
| 57 | return preposition_query(*this); | ||
| 58 | } | ||
| 59 | |||
| 50 | }; | 60 | }; |
| 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 @@ | |||
| 2 | #define DATA_H_C4AEC3DD | 2 | #define DATA_H_C4AEC3DD |
| 3 | 3 | ||
| 4 | #include <sqlite3.h> | 4 | #include <sqlite3.h> |
| 5 | #include <stdexcept> | ||
| 6 | 5 | ||
| 7 | namespace verbly { | 6 | namespace verbly { |
| 8 | 7 | ||
| @@ -12,10 +11,13 @@ namespace verbly { | |||
| 12 | class noun; | 11 | class noun; |
| 13 | class verb; | 12 | class verb; |
| 14 | class adverb; | 13 | class adverb; |
| 14 | class frame; | ||
| 15 | class adjective_query; | 15 | class adjective_query; |
| 16 | class adverb_query; | 16 | class adverb_query; |
| 17 | class noun_query; | 17 | class noun_query; |
| 18 | class verb_query; | 18 | class verb_query; |
| 19 | class frame_query; | ||
| 20 | class preposition_query; | ||
| 19 | 21 | ||
| 20 | class data { | 22 | class data { |
| 21 | private: | 23 | private: |
| @@ -25,6 +27,8 @@ namespace verbly { | |||
| 25 | friend class noun_query; | 27 | friend class noun_query; |
| 26 | friend class verb_query; | 28 | friend class verb_query; |
| 27 | friend class adverb_query; | 29 | friend class adverb_query; |
| 30 | friend class frame_query; | ||
| 31 | friend class preposition_query; | ||
| 28 | 32 | ||
| 29 | public: | 33 | public: |
| 30 | data(std::string datafile); | 34 | data(std::string datafile); |
| @@ -41,9 +45,302 @@ namespace verbly { | |||
| 41 | adjective_query adjectives() const; | 45 | adjective_query adjectives() const; |
| 42 | adverb_query adverbs() const; | 46 | adverb_query adverbs() const; |
| 43 | noun_query nouns() const; | 47 | noun_query nouns() const; |
| 48 | frame_query frames() const; | ||
| 49 | preposition_query prepositions() const; | ||
| 44 | 50 | ||
| 45 | }; | 51 | }; |
| 46 | 52 | ||
| 53 | template <class T> | ||
| 54 | class filter { | ||
| 55 | public: | ||
| 56 | enum class type { | ||
| 57 | singleton, | ||
| 58 | group | ||
| 59 | }; | ||
| 60 | |||
| 61 | typedef filter<T> value_type; | ||
| 62 | |||
| 63 | type get_type() const | ||
| 64 | { | ||
| 65 | return _type; | ||
| 66 | } | ||
| 67 | |||
| 68 | filter(const filter<T>& other) | ||
| 69 | { | ||
| 70 | _type = other._type; | ||
| 71 | _notlogic = other._notlogic; | ||
| 72 | |||
| 73 | switch (_type) | ||
| 74 | { | ||
| 75 | case type::singleton: | ||
| 76 | { | ||
| 77 | new(&_singleton.elem) T(other._singleton.elem); | ||
| 78 | |||
| 79 | break; | ||
| 80 | } | ||
| 81 | |||
| 82 | case type::group: | ||
| 83 | { | ||
| 84 | new(&_group.elems) std::list<filter<T>>(other._group.elems); | ||
| 85 | _group.orlogic = other._group.orlogic; | ||
| 86 | |||
| 87 | break; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | filter<T>& operator=(const filter<T>& other) | ||
| 93 | { | ||
| 94 | this->~filter(); | ||
| 95 | |||
| 96 | _type = other._type; | ||
| 97 | _notlogic = other._notlogic; | ||
| 98 | |||
| 99 | switch (_type) | ||
| 100 | { | ||
| 101 | case type::singleton: | ||
| 102 | { | ||
| 103 | new(&_singleton.elem) T(other._singleton.elem); | ||
| 104 | |||
| 105 | break; | ||
| 106 | } | ||
| 107 | |||
| 108 | case type::group: | ||
| 109 | { | ||
| 110 | new(&_group.elems) std::list<filter<T>>(other._group.elems); | ||
| 111 | _group.orlogic = other._group.orlogic; | ||
| 112 | |||
| 113 | break; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | return *this; | ||
| 118 | } | ||
| 119 | |||
| 120 | ~filter() | ||
| 121 | { | ||
| 122 | switch (_type) | ||
| 123 | { | ||
| 124 | case type::singleton: | ||
| 125 | { | ||
| 126 | _singleton.elem.~T(); | ||
| 127 | |||
| 128 | break; | ||
| 129 | } | ||
| 130 | |||
| 131 | case type::group: | ||
| 132 | { | ||
| 133 | using list_type = std::list<filter<T>>; | ||
| 134 | _group.elems.~list_type(); | ||
| 135 | |||
| 136 | break; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | bool get_notlogic() const | ||
| 142 | { | ||
| 143 | return _notlogic; | ||
| 144 | } | ||
| 145 | |||
| 146 | void set_notlogic(bool _nl) | ||
| 147 | { | ||
| 148 | _notlogic = _nl; | ||
| 149 | } | ||
| 150 | |||
| 151 | std::list<T> inorder_flatten() const | ||
| 152 | { | ||
| 153 | std::list<T> result; | ||
| 154 | |||
| 155 | if (_type == type::singleton) | ||
| 156 | { | ||
| 157 | result.push_back(_singleton.elem); | ||
| 158 | } else if (_type == type::group) | ||
| 159 | { | ||
| 160 | for (auto elem : _group.elems) | ||
| 161 | { | ||
| 162 | auto l = elem.inorder_flatten(); | ||
| 163 | result.insert(std::end(result), std::begin(l), std::end(l)); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | return result; | ||
| 168 | } | ||
| 169 | |||
| 170 | std::set<T> uniq_flatten() const | ||
| 171 | { | ||
| 172 | std::set<T> result; | ||
| 173 | |||
| 174 | if (_type == type::singleton) | ||
| 175 | { | ||
| 176 | result.insert(_singleton.elem); | ||
| 177 | } else if (_type == type::group) | ||
| 178 | { | ||
| 179 | for (auto elem : _group.elems) | ||
| 180 | { | ||
| 181 | auto l = elem.uniq_flatten(); | ||
| 182 | result.insert(std::begin(l), std::end(l)); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | return result; | ||
| 187 | } | ||
| 188 | |||
| 189 | void clean() | ||
| 190 | { | ||
| 191 | if (_type == type::group) | ||
| 192 | { | ||
| 193 | std::list<typename std::list<filter<T>>::iterator> toremove; | ||
| 194 | for (auto it = _group.elems.begin(); it != _group.elems.end(); it++) | ||
| 195 | { | ||
| 196 | it->clean(); | ||
| 197 | |||
| 198 | if (it->get_type() == type::group) | ||
| 199 | { | ||
| 200 | if (it->_group.elems.size() == 0) | ||
| 201 | { | ||
| 202 | toremove.push_back(it); | ||
| 203 | } else if (it->_group.elems.size() == 1) | ||
| 204 | { | ||
| 205 | bool truelogic = it->_notlogic != it->_group.elems.front()._notlogic; | ||
| 206 | *it = it->_group.elems.front(); | ||
| 207 | it->_notlogic = truelogic; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | for (auto rem : toremove) | ||
| 213 | { | ||
| 214 | _group.elems.erase(rem); | ||
| 215 | } | ||
| 216 | |||
| 217 | if (_group.elems.size() == 1) | ||
| 218 | { | ||
| 219 | bool truelogic = _notlogic != _group.elems.front()._notlogic; | ||
| 220 | *this = _group.elems.front(); | ||
| 221 | _notlogic = truelogic; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | // Singleton | ||
| 227 | filter(T _elem, bool _notlogic = false) : _type(type::singleton) | ||
| 228 | { | ||
| 229 | new(&_singleton.elem) T(_elem); | ||
| 230 | this->_notlogic = _notlogic; | ||
| 231 | } | ||
| 232 | |||
| 233 | filter<T>& operator=(T _elem) | ||
| 234 | { | ||
| 235 | *this = filter<T>{_elem}; | ||
| 236 | |||
| 237 | return *this; | ||
| 238 | } | ||
| 239 | |||
| 240 | T get_elem() const | ||
| 241 | { | ||
| 242 | assert(_type == type::singleton); | ||
| 243 | |||
| 244 | return _singleton.elem; | ||
| 245 | } | ||
| 246 | |||
| 247 | void set_elem(T _elem) | ||
| 248 | { | ||
| 249 | assert(_type == type::singleton); | ||
| 250 | |||
| 251 | _singleton.elem = _elem; | ||
| 252 | } | ||
| 253 | |||
| 254 | // Group | ||
| 255 | typedef typename std::list<filter<T>>::iterator iterator; | ||
| 256 | |||
| 257 | filter() : _type(type::group) | ||
| 258 | { | ||
| 259 | new(&_group.elems) std::list<filter<T>>(); | ||
| 260 | _group.orlogic = false; | ||
| 261 | } | ||
| 262 | |||
| 263 | filter(std::initializer_list<filter<T>> _init) : _type(type::group) | ||
| 264 | { | ||
| 265 | new(&_group.elems) std::list<filter<T>>(_init); | ||
| 266 | _group.orlogic = false; | ||
| 267 | } | ||
| 268 | |||
| 269 | iterator begin() | ||
| 270 | { | ||
| 271 | assert(_type == type::group); | ||
| 272 | |||
| 273 | return _group.elems.begin(); | ||
| 274 | } | ||
| 275 | |||
| 276 | iterator end() | ||
| 277 | { | ||
| 278 | assert(_type == type::group); | ||
| 279 | |||
| 280 | return _group.elems.end(); | ||
| 281 | } | ||
| 282 | |||
| 283 | filter<T>& operator<<(filter<T> _elem) | ||
| 284 | { | ||
| 285 | assert(_type == type::group); | ||
| 286 | |||
| 287 | _group.elems.push_back(_elem); | ||
| 288 | |||
| 289 | return *this; | ||
| 290 | } | ||
| 291 | |||
| 292 | void push_back(filter<T> _elem) | ||
| 293 | { | ||
| 294 | assert(_type == type::group); | ||
| 295 | |||
| 296 | _group.elems.push_back(_elem); | ||
| 297 | } | ||
| 298 | |||
| 299 | bool get_orlogic() const | ||
| 300 | { | ||
| 301 | assert(_type == type::group); | ||
| 302 | |||
| 303 | return _group.orlogic; | ||
| 304 | } | ||
| 305 | |||
| 306 | void set_orlogic(bool _ol) | ||
| 307 | { | ||
| 308 | assert(_type == type::group); | ||
| 309 | |||
| 310 | _group.orlogic = _ol; | ||
| 311 | } | ||
| 312 | |||
| 313 | bool empty() const | ||
| 314 | { | ||
| 315 | if (_type == type::group) | ||
| 316 | { | ||
| 317 | return _group.elems.empty(); | ||
| 318 | } else { | ||
| 319 | return false; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | int size() const | ||
| 324 | { | ||
| 325 | assert(_type == type::group); | ||
| 326 | |||
| 327 | return _group.elems.size(); | ||
| 328 | } | ||
| 329 | |||
| 330 | private: | ||
| 331 | type _type; | ||
| 332 | bool _notlogic = false; | ||
| 333 | union { | ||
| 334 | struct { | ||
| 335 | T elem; | ||
| 336 | } _singleton; | ||
| 337 | struct { | ||
| 338 | std::list<filter<T>> elems; | ||
| 339 | bool orlogic; | ||
| 340 | } _group; | ||
| 341 | }; | ||
| 342 | }; | ||
| 343 | |||
| 47 | }; | 344 | }; |
| 48 | 345 | ||
| 49 | #endif /* end of include guard: DATA_H_C4AEC3DD */ | 346 | #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 @@ | |||
| 1 | #include "verbly.h" | ||
| 2 | |||
| 3 | namespace verbly { | ||
| 4 | |||
| 5 | frame::selrestr::type frame::selrestr::get_type() const | ||
| 6 | { | ||
| 7 | return _type; | ||
| 8 | } | ||
| 9 | |||
| 10 | frame::selrestr::selrestr(const selrestr& other) | ||
| 11 | { | ||
| 12 | _type = other._type; | ||
| 13 | |||
| 14 | switch (_type) | ||
| 15 | { | ||
| 16 | case frame::selrestr::type::singleton: | ||
| 17 | { | ||
| 18 | _singleton.pos = other._singleton.pos; | ||
| 19 | new(&_singleton.restriction) std::string(other._singleton.restriction); | ||
| 20 | |||
| 21 | break; | ||
| 22 | } | ||
| 23 | |||
| 24 | case frame::selrestr::type::group: | ||
| 25 | { | ||
| 26 | new(&_group.children) std::list<selrestr>(other._group.children); | ||
| 27 | _group.orlogic = other._group.orlogic; | ||
| 28 | |||
| 29 | break; | ||
| 30 | } | ||
| 31 | |||
| 32 | case frame::selrestr::type::empty: | ||
| 33 | { | ||
| 34 | // Nothing! | ||
| 35 | |||
| 36 | break; | ||
| 37 | } | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | frame::selrestr::~selrestr() | ||
| 42 | { | ||
| 43 | switch (_type) | ||
| 44 | { | ||
| 45 | case frame::selrestr::type::singleton: | ||
| 46 | { | ||
| 47 | using string_type = std::string; | ||
| 48 | _singleton.restriction.~string_type(); | ||
| 49 | |||
| 50 | break; | ||
| 51 | } | ||
| 52 | |||
| 53 | case frame::selrestr::type::group: | ||
| 54 | { | ||
| 55 | using list_type = std::list<selrestr>; | ||
| 56 | _group.children.~list_type(); | ||
| 57 | |||
| 58 | break; | ||
| 59 | } | ||
| 60 | |||
| 61 | case frame::selrestr::type::empty: | ||
| 62 | { | ||
| 63 | // Nothing! | ||
| 64 | |||
| 65 | break; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | frame::selrestr& frame::selrestr::operator=(const selrestr& other) | ||
| 71 | { | ||
| 72 | this->~selrestr(); | ||
| 73 | |||
| 74 | _type = other._type; | ||
| 75 | |||
| 76 | switch (_type) | ||
| 77 | { | ||
| 78 | case frame::selrestr::type::singleton: | ||
| 79 | { | ||
| 80 | _singleton.pos = other._singleton.pos; | ||
| 81 | new(&_singleton.restriction) std::string(other._singleton.restriction); | ||
| 82 | |||
| 83 | break; | ||
| 84 | } | ||
| 85 | |||
| 86 | case frame::selrestr::type::group: | ||
| 87 | { | ||
| 88 | new(&_group.children) std::list<selrestr>(other._group.children); | ||
| 89 | _group.orlogic = other._group.orlogic; | ||
| 90 | |||
| 91 | break; | ||
| 92 | } | ||
| 93 | |||
| 94 | case frame::selrestr::type::empty: | ||
| 95 | { | ||
| 96 | // Nothing! | ||
| 97 | |||
| 98 | break; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | return *this; | ||
| 103 | } | ||
| 104 | |||
| 105 | frame::selrestr::selrestr() : _type(frame::selrestr::type::empty) | ||
| 106 | { | ||
| 107 | |||
| 108 | } | ||
| 109 | |||
| 110 | frame::selrestr::selrestr(std::string restriction, bool pos) : _type(frame::selrestr::type::singleton) | ||
| 111 | { | ||
| 112 | new(&_singleton.restriction) std::string(restriction); | ||
| 113 | _singleton.pos = pos; | ||
| 114 | } | ||
| 115 | |||
| 116 | std::string frame::selrestr::get_restriction() const | ||
| 117 | { | ||
| 118 | assert(_type == frame::selrestr::type::singleton); | ||
| 119 | |||
| 120 | return _singleton.restriction; | ||
| 121 | } | ||
| 122 | |||
| 123 | bool frame::selrestr::get_pos() const | ||
| 124 | { | ||
| 125 | assert(_type == frame::selrestr::type::singleton); | ||
| 126 | |||
| 127 | return _singleton.pos; | ||
| 128 | } | ||
| 129 | |||
| 130 | frame::selrestr::selrestr(std::list<selrestr> children, bool orlogic) : _type(frame::selrestr::type::group) | ||
| 131 | { | ||
| 132 | new(&_group.children) std::list<selrestr>(children); | ||
| 133 | _group.orlogic = orlogic; | ||
| 134 | } | ||
| 135 | |||
| 136 | std::list<frame::selrestr> frame::selrestr::get_children() const | ||
| 137 | { | ||
| 138 | assert(_type == frame::selrestr::type::group); | ||
| 139 | |||
| 140 | return _group.children; | ||
| 141 | } | ||
| 142 | |||
| 143 | std::list<frame::selrestr>::const_iterator frame::selrestr::begin() const | ||
| 144 | { | ||
| 145 | assert(_type == frame::selrestr::type::group); | ||
| 146 | |||
| 147 | return _group.children.begin(); | ||
| 148 | } | ||
| 149 | |||
| 150 | std::list<frame::selrestr>::const_iterator frame::selrestr::end() const | ||
| 151 | { | ||
| 152 | assert(_type == frame::selrestr::type::group); | ||
| 153 | |||
| 154 | return _group.children.end(); | ||
| 155 | } | ||
| 156 | |||
| 157 | bool frame::selrestr::get_orlogic() const | ||
| 158 | { | ||
| 159 | assert(_type == frame::selrestr::type::group); | ||
| 160 | |||
| 161 | return _group.orlogic; | ||
| 162 | } | ||
| 163 | |||
| 164 | frame::part::type frame::part::get_type() const | ||
| 165 | { | ||
| 166 | return _type; | ||
| 167 | } | ||
| 168 | |||
| 169 | frame::part::part() | ||
| 170 | { | ||
| 171 | |||
| 172 | } | ||
| 173 | |||
| 174 | frame::part::part(const part& other) | ||
| 175 | { | ||
| 176 | _type = other._type; | ||
| 177 | |||
| 178 | switch (_type) | ||
| 179 | { | ||
| 180 | case frame::part::type::noun_phrase: | ||
| 181 | { | ||
| 182 | new(&_noun_phrase.role) std::string(other._noun_phrase.role); | ||
| 183 | new(&_noun_phrase.selrestrs) selrestr(other._noun_phrase.selrestrs); | ||
| 184 | new(&_noun_phrase.synrestrs) std::set<std::string>(other._noun_phrase.synrestrs); | ||
| 185 | |||
| 186 | break; | ||
| 187 | } | ||
| 188 | |||
| 189 | case frame::part::type::literal_preposition: | ||
| 190 | { | ||
| 191 | new(&_literal_preposition.choices) std::vector<std::string>(other._literal_preposition.choices); | ||
| 192 | |||
| 193 | break; | ||
| 194 | } | ||
| 195 | |||
| 196 | case frame::part::type::selection_preposition: | ||
| 197 | { | ||
| 198 | new(&_selection_preposition.preprestrs) std::vector<std::string>(other._selection_preposition.preprestrs); | ||
| 199 | |||
| 200 | break; | ||
| 201 | } | ||
| 202 | |||
| 203 | case frame::part::type::literal: | ||
| 204 | { | ||
| 205 | new(&_literal.lexval) std::string(other._literal.lexval); | ||
| 206 | |||
| 207 | break; | ||
| 208 | } | ||
| 209 | |||
| 210 | default: | ||
| 211 | { | ||
| 212 | // Nothing! | ||
| 213 | |||
| 214 | break; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | frame::part::~part() | ||
| 220 | { | ||
| 221 | switch (_type) | ||
| 222 | { | ||
| 223 | case frame::part::type::noun_phrase: | ||
| 224 | { | ||
| 225 | using string_type = std::string; | ||
| 226 | using set_type = std::set<std::string>; | ||
| 227 | |||
| 228 | _noun_phrase.role.~string_type(); | ||
| 229 | _noun_phrase.selrestrs.~selrestr(); | ||
| 230 | _noun_phrase.synrestrs.~set_type(); | ||
| 231 | |||
| 232 | break; | ||
| 233 | } | ||
| 234 | |||
| 235 | case frame::part::type::literal_preposition: | ||
| 236 | { | ||
| 237 | using vector_type = std::vector<std::string>; | ||
| 238 | _literal_preposition.choices.~vector_type(); | ||
| 239 | |||
| 240 | break; | ||
| 241 | } | ||
| 242 | |||
| 243 | case frame::part::type::selection_preposition: | ||
| 244 | { | ||
| 245 | using vector_type = std::vector<std::string>; | ||
| 246 | _selection_preposition.preprestrs.~vector_type(); | ||
| 247 | |||
| 248 | break; | ||
| 249 | } | ||
| 250 | |||
| 251 | case frame::part::type::literal: | ||
| 252 | { | ||
| 253 | using string_type = std::string; | ||
| 254 | _literal.lexval.~string_type(); | ||
| 255 | |||
| 256 | break; | ||
| 257 | } | ||
| 258 | |||
| 259 | default: | ||
| 260 | { | ||
| 261 | // Nothing! | ||
| 262 | |||
| 263 | break; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | std::string frame::part::get_role() const | ||
| 269 | { | ||
| 270 | assert(_type == frame::part::type::noun_phrase); | ||
| 271 | |||
| 272 | return _noun_phrase.role; | ||
| 273 | } | ||
| 274 | |||
| 275 | frame::selrestr frame::part::get_selrestrs() const | ||
| 276 | { | ||
| 277 | assert(_type == frame::part::type::noun_phrase); | ||
| 278 | |||
| 279 | return _noun_phrase.selrestrs; | ||
| 280 | } | ||
| 281 | |||
| 282 | std::set<std::string> frame::part::get_synrestrs() const | ||
| 283 | { | ||
| 284 | assert(_type == frame::part::type::noun_phrase); | ||
| 285 | |||
| 286 | return _noun_phrase.synrestrs; | ||
| 287 | } | ||
| 288 | |||
| 289 | std::vector<std::string> frame::part::get_choices() const | ||
| 290 | { | ||
| 291 | assert(_type == frame::part::type::literal_preposition); | ||
| 292 | |||
| 293 | return _literal_preposition.choices; | ||
| 294 | } | ||
| 295 | |||
| 296 | std::vector<std::string> frame::part::get_preprestrs() const | ||
| 297 | { | ||
| 298 | assert(_type == frame::part::type::selection_preposition); | ||
| 299 | |||
| 300 | return _selection_preposition.preprestrs; | ||
| 301 | } | ||
| 302 | |||
| 303 | std::string frame::part::get_literal() const | ||
| 304 | { | ||
| 305 | assert(_type == frame::part::type::literal); | ||
| 306 | |||
| 307 | return _literal.lexval; | ||
| 308 | } | ||
| 309 | |||
| 310 | std::vector<frame::part> frame::parts() const | ||
| 311 | { | ||
| 312 | return _parts; | ||
| 313 | } | ||
| 314 | |||
| 315 | std::map<std::string, frame::selrestr> frame::roles() const | ||
| 316 | { | ||
| 317 | return _roles; | ||
| 318 | } | ||
| 319 | |||
| 320 | }; | ||
| 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 @@ | |||
| 1 | #ifndef FRAME_H_9A5D90FE | ||
| 2 | #define FRAME_H_9A5D90FE | ||
| 3 | |||
| 4 | namespace verbly { | ||
| 5 | |||
| 6 | class frame_query; | ||
| 7 | |||
| 8 | class frame { | ||
| 9 | public: | ||
| 10 | class selrestr { | ||
| 11 | public: | ||
| 12 | enum class type { | ||
| 13 | empty, | ||
| 14 | singleton, | ||
| 15 | group | ||
| 16 | }; | ||
| 17 | |||
| 18 | type get_type() const; | ||
| 19 | selrestr(const selrestr& other); | ||
| 20 | ~selrestr(); | ||
| 21 | selrestr& operator=(const selrestr& other); | ||
| 22 | |||
| 23 | // Empty | ||
| 24 | selrestr(); | ||
| 25 | |||
| 26 | // Singleton | ||
| 27 | selrestr(std::string restriction, bool pos); | ||
| 28 | std::string get_restriction() const; | ||
| 29 | bool get_pos() const; | ||
| 30 | |||
| 31 | // Group | ||
| 32 | selrestr(std::list<selrestr> children, bool orlogic); | ||
| 33 | std::list<selrestr> get_children() const; | ||
| 34 | std::list<selrestr>::const_iterator begin() const; | ||
| 35 | std::list<selrestr>::const_iterator end() const; | ||
| 36 | bool get_orlogic() const; | ||
| 37 | |||
| 38 | private: | ||
| 39 | union { | ||
| 40 | struct { | ||
| 41 | bool pos; | ||
| 42 | std::string restriction; | ||
| 43 | } _singleton; | ||
| 44 | struct { | ||
| 45 | std::list<selrestr> children; | ||
| 46 | bool orlogic; | ||
| 47 | } _group; | ||
| 48 | }; | ||
| 49 | type _type; | ||
| 50 | }; | ||
| 51 | |||
| 52 | class part { | ||
| 53 | public: | ||
| 54 | enum class type { | ||
| 55 | noun_phrase, | ||
| 56 | verb, | ||
| 57 | literal_preposition, | ||
| 58 | selection_preposition, | ||
| 59 | adjective, | ||
| 60 | adverb, | ||
| 61 | literal | ||
| 62 | }; | ||
| 63 | |||
| 64 | type get_type() const; | ||
| 65 | part(const part& other); | ||
| 66 | ~part(); | ||
| 67 | |||
| 68 | // Noun phrase | ||
| 69 | std::string get_role() const; | ||
| 70 | selrestr get_selrestrs() const; | ||
| 71 | std::set<std::string> get_synrestrs() const; | ||
| 72 | |||
| 73 | // Literal preposition | ||
| 74 | std::vector<std::string> get_choices() const; | ||
| 75 | |||
| 76 | // Selection preposition | ||
| 77 | std::vector<std::string> get_preprestrs() const; | ||
| 78 | |||
| 79 | // Literal | ||
| 80 | std::string get_literal() const; | ||
| 81 | |||
| 82 | private: | ||
| 83 | friend class frame_query; | ||
| 84 | |||
| 85 | part(); | ||
| 86 | |||
| 87 | union { | ||
| 88 | struct { | ||
| 89 | std::string role; | ||
| 90 | selrestr selrestrs; | ||
| 91 | std::set<std::string> synrestrs; | ||
| 92 | } _noun_phrase; | ||
| 93 | struct { | ||
| 94 | std::vector<std::string> choices; | ||
| 95 | } _literal_preposition; | ||
| 96 | struct { | ||
| 97 | std::vector<std::string> preprestrs; | ||
| 98 | } _selection_preposition; | ||
| 99 | struct { | ||
| 100 | std::string lexval; | ||
| 101 | } _literal; | ||
| 102 | }; | ||
| 103 | type _type; | ||
| 104 | }; | ||
| 105 | |||
| 106 | std::vector<part> parts() const; | ||
| 107 | std::map<std::string, selrestr> roles() const; | ||
| 108 | |||
| 109 | private: | ||
| 110 | friend class frame_query; | ||
| 111 | |||
| 112 | std::vector<part> _parts; | ||
| 113 | std::map<std::string, selrestr> _roles; | ||
| 114 | }; | ||
| 115 | |||
| 116 | }; | ||
| 117 | |||
| 118 | #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 @@ | |||
| 1 | #include "verbly.h" | ||
| 2 | #include <json.hpp> | ||
| 3 | |||
| 4 | using json = nlohmann::json; | ||
| 5 | |||
| 6 | namespace verbly { | ||
| 7 | |||
| 8 | frame_query::frame_query(const data& _data) : _data(_data) | ||
| 9 | { | ||
| 10 | |||
| 11 | } | ||
| 12 | |||
| 13 | frame_query& frame_query::for_verb(const verb& _v) | ||
| 14 | { | ||
| 15 | _for_verb.push_back(_v); | ||
| 16 | |||
| 17 | return *this; | ||
| 18 | } | ||
| 19 | |||
| 20 | frame::selrestr parse_selrestr(const json data) | ||
| 21 | { | ||
| 22 | if (data.find("children") != data.end()) | ||
| 23 | { | ||
| 24 | std::list<frame::selrestr> children; | ||
| 25 | std::transform(std::begin(data["children"]), std::end(data["children"]), std::back_inserter(children), &parse_selrestr); | ||
| 26 | |||
| 27 | return frame::selrestr{children, data["logic"] == "or"}; | ||
| 28 | } else if (data.find("type") != data.end()) | ||
| 29 | { | ||
| 30 | return frame::selrestr{data["type"].get<std::string>(), data["pos"].get<bool>()}; | ||
| 31 | } else { | ||
| 32 | return frame::selrestr{}; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | std::list<frame> frame_query::run() const | ||
| 37 | { | ||
| 38 | std::stringstream construct; | ||
| 39 | construct << "SELECT frames.data, groups.data FROM frames INNER JOIN groups ON frames.group_id = groups.group_id"; | ||
| 40 | |||
| 41 | if (!_for_verb.empty()) | ||
| 42 | { | ||
| 43 | std::list<std::string> clauses(_for_verb.size(), "verb_id = @VERID"); | ||
| 44 | construct << " WHERE frames.group_id IN (SELECT group_id FROM verb_groups WHERE "; | ||
| 45 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); | ||
| 46 | construct << ")"; | ||
| 47 | } | ||
| 48 | |||
| 49 | sqlite3_stmt* ppstmt; | ||
| 50 | std::string query = construct.str(); | ||
| 51 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 52 | { | ||
| 53 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 54 | } | ||
| 55 | |||
| 56 | for (auto verb : _for_verb) | ||
| 57 | { | ||
| 58 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VERID"), verb._id); | ||
| 59 | } | ||
| 60 | |||
| 61 | std::list<frame> output; | ||
| 62 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 63 | { | ||
| 64 | frame f; | ||
| 65 | |||
| 66 | std::string fdatat(reinterpret_cast<const char*>(sqlite3_column_blob(ppstmt, 0))); | ||
| 67 | const json fdata = json::parse(fdatat); | ||
| 68 | for (const auto& part : fdata) | ||
| 69 | { | ||
| 70 | frame::part p; | ||
| 71 | |||
| 72 | if (part["type"] == "np") | ||
| 73 | { | ||
| 74 | p._type = frame::part::type::noun_phrase; | ||
| 75 | new(&p._noun_phrase.role) std::string(part["role"].get<std::string>()); | ||
| 76 | new(&p._noun_phrase.selrestrs) frame::selrestr(parse_selrestr(part["selrestrs"])); | ||
| 77 | new(&p._noun_phrase.synrestrs) std::set<std::string>(); | ||
| 78 | for (auto synrestr : part["synrestrs"]) | ||
| 79 | { | ||
| 80 | p._noun_phrase.synrestrs.insert(synrestr.get<std::string>()); | ||
| 81 | } | ||
| 82 | } else if (part["type"] == "pp") | ||
| 83 | { | ||
| 84 | if (!part["values"].empty()) | ||
| 85 | { | ||
| 86 | p._type = frame::part::type::literal_preposition; | ||
| 87 | new(&p._literal_preposition.choices) std::vector<std::string>(); | ||
| 88 | for (auto choice : part["values"]) | ||
| 89 | { | ||
| 90 | p._literal_preposition.choices.push_back(choice.get<std::string>()); | ||
| 91 | } | ||
| 92 | } else if (!part["preprestrs"].empty()) | ||
| 93 | { | ||
| 94 | p._type = frame::part::type::selection_preposition; | ||
| 95 | new(&p._selection_preposition.preprestrs) std::vector<std::string>(); | ||
| 96 | for (auto preprestr : part["preprestrs"]) | ||
| 97 | { | ||
| 98 | p._selection_preposition.preprestrs.push_back(preprestr.get<std::string>()); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | } else if (part["type"] == "v") | ||
| 102 | { | ||
| 103 | p._type = frame::part::type::verb; | ||
| 104 | } else if (part["type"] == "adj") | ||
| 105 | { | ||
| 106 | p._type = frame::part::type::adjective; | ||
| 107 | } else if (part["type"] == "adv") | ||
| 108 | { | ||
| 109 | p._type = frame::part::type::adverb; | ||
| 110 | } else if (part["type"] == "lex") | ||
| 111 | { | ||
| 112 | p._type = frame::part::type::literal; | ||
| 113 | new(&p._literal.lexval) std::string(part["value"].get<std::string>()); | ||
| 114 | } | ||
| 115 | |||
| 116 | f._parts.push_back(p); | ||
| 117 | } | ||
| 118 | |||
| 119 | std::string rdatat(reinterpret_cast<const char*>(sqlite3_column_blob(ppstmt, 1))); | ||
| 120 | const json rdata = json::parse(rdatat); | ||
| 121 | for (const auto& role : rdata) | ||
| 122 | { | ||
| 123 | std::string rt = role["type"]; | ||
| 124 | frame::selrestr rs; | ||
| 125 | |||
| 126 | if (role.find("selrestrs") != role.end()) | ||
| 127 | { | ||
| 128 | rs = parse_selrestr(role["selrestrs"]); | ||
| 129 | } | ||
| 130 | |||
| 131 | f._roles[rt] = rs; | ||
| 132 | } | ||
| 133 | |||
| 134 | output.push_back(f); | ||
| 135 | } | ||
| 136 | |||
| 137 | sqlite3_finalize(ppstmt); | ||
| 138 | |||
| 139 | return output; | ||
| 140 | } | ||
| 141 | |||
| 142 | }; | ||
| 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 @@ | |||
| 1 | #ifndef FRAME_QUERY_H_334B9D47 | ||
| 2 | #define FRAME_QUERY_H_334B9D47 | ||
| 3 | |||
| 4 | namespace verbly { | ||
| 5 | |||
| 6 | class frame_query { | ||
| 7 | public: | ||
| 8 | frame_query(const data& _data); | ||
| 9 | |||
| 10 | frame_query& for_verb(const verb& _v); | ||
| 11 | |||
| 12 | std::list<frame> run() const; | ||
| 13 | |||
| 14 | private: | ||
| 15 | const data& _data; | ||
| 16 | std::list<verb> _for_verb; | ||
| 17 | }; | ||
| 18 | |||
| 19 | }; | ||
| 20 | |||
| 21 | #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 @@ | |||
| 1 | #include "verbly.h" | 1 | #include "verbly.h" |
| 2 | #include <set> | ||
| 3 | #include <iostream> | ||
| 2 | 4 | ||
| 3 | namespace verbly { | 5 | namespace verbly { |
| 4 | 6 | ||
| 7 | noun::noun() | ||
| 8 | { | ||
| 9 | |||
| 10 | } | ||
| 11 | |||
| 5 | noun::noun(const data& _data, int _id) : word(_data, _id) | 12 | noun::noun(const data& _data, int _id) : word(_data, _id) |
| 6 | { | 13 | { |
| 7 | 14 | ||
| @@ -9,1036 +16,147 @@ namespace verbly { | |||
| 9 | 16 | ||
| 10 | std::string noun::base_form() const | 17 | std::string noun::base_form() const |
| 11 | { | 18 | { |
| 19 | assert(_valid == true); | ||
| 20 | |||
| 12 | return _singular; | 21 | return _singular; |
| 13 | } | 22 | } |
| 14 | 23 | ||
| 15 | std::string noun::singular_form() const | 24 | std::string noun::singular_form() const |
| 16 | { | 25 | { |
| 26 | assert(_valid == true); | ||
| 27 | |||
| 17 | return _singular; | 28 | return _singular; |
| 18 | } | 29 | } |
| 19 | 30 | ||
| 20 | std::string noun::plural_form() const | 31 | std::string noun::plural_form() const |
| 21 | { | 32 | { |
| 33 | assert(_valid == true); | ||
| 34 | |||
| 22 | return _plural; | 35 | return _plural; |
| 23 | } | 36 | } |
| 24 | 37 | ||
| 25 | bool noun::has_plural_form() const | 38 | bool noun::has_plural_form() const |
| 26 | { | 39 | { |
| 40 | assert(_valid == true); | ||
| 41 | |||
| 27 | return !_plural.empty(); | 42 | return !_plural.empty(); |
| 28 | } | 43 | } |
| 29 | 44 | ||
| 30 | noun_query noun::hypernyms() const | 45 | noun_query noun::hypernyms() const |
| 31 | { | 46 | { |
| 32 | return _data.nouns().hypernym_of(*this); | 47 | assert(_valid == true); |
| 33 | } | ||
| 34 | |||
| 35 | noun_query noun::hyponyms() const | ||
| 36 | { | ||
| 37 | return _data.nouns().hyponym_of(*this); | ||
| 38 | } | ||
| 39 | |||
| 40 | noun_query noun::part_meronyms() const | ||
| 41 | { | ||
| 42 | return _data.nouns().part_meronym_of(*this); | ||
| 43 | } | ||
| 44 | |||
| 45 | noun_query noun::part_holonyms() const | ||
| 46 | { | ||
| 47 | return _data.nouns().part_holonym_of(*this); | ||
| 48 | } | ||
| 49 | |||
| 50 | noun_query noun::substance_meronyms() const | ||
| 51 | { | ||
| 52 | return _data.nouns().substance_meronym_of(*this); | ||
| 53 | } | ||
| 54 | |||
| 55 | noun_query noun::substance_holonyms() const | ||
| 56 | { | ||
| 57 | return _data.nouns().substance_holonym_of(*this); | ||
| 58 | } | ||
| 59 | |||
| 60 | noun_query noun::member_meronyms() const | ||
| 61 | { | ||
| 62 | return _data.nouns().member_meronym_of(*this); | ||
| 63 | } | ||
| 64 | |||
| 65 | noun_query noun::member_holonyms() const | ||
| 66 | { | ||
| 67 | return _data.nouns().member_holonym_of(*this); | ||
| 68 | } | ||
| 69 | |||
| 70 | noun_query noun::classes() const | ||
| 71 | { | ||
| 72 | return _data.nouns().class_of(*this); | ||
| 73 | } | ||
| 74 | |||
| 75 | noun_query noun::instances() const | ||
| 76 | { | ||
| 77 | return _data.nouns().instance_of(*this); | ||
| 78 | } | ||
| 79 | |||
| 80 | noun_query noun::synonyms() const | ||
| 81 | { | ||
| 82 | return _data.nouns().synonym_of(*this); | ||
| 83 | } | ||
| 84 | |||
| 85 | noun_query noun::antonyms() const | ||
| 86 | { | ||
| 87 | return _data.nouns().antonym_of(*this); | ||
| 88 | } | ||
| 89 | |||
| 90 | adjective_query noun::pertainyms() const | ||
| 91 | { | ||
| 92 | return _data.adjectives().pertainym_of(*this); | ||
| 93 | } | ||
| 94 | |||
| 95 | adjective_query noun::variations() const | ||
| 96 | { | ||
| 97 | return _data.adjectives().variant_of(*this); | ||
| 98 | } | ||
| 99 | |||
| 100 | noun_query::noun_query(const data& _data) : _data(_data) | ||
| 101 | { | ||
| 102 | |||
| 103 | } | ||
| 104 | |||
| 105 | noun_query& noun_query::limit(int _limit) | ||
| 106 | { | ||
| 107 | if ((_limit > 0) || (_limit == unlimited)) | ||
| 108 | { | ||
| 109 | this->_limit = _limit; | ||
| 110 | } | ||
| 111 | |||
| 112 | return *this; | ||
| 113 | } | ||
| 114 | |||
| 115 | noun_query& noun_query::random(bool _random) | ||
| 116 | { | ||
| 117 | this->_random = _random; | ||
| 118 | |||
| 119 | return *this; | ||
| 120 | } | ||
| 121 | |||
| 122 | noun_query& noun_query::except(const noun& _word) | ||
| 123 | { | ||
| 124 | _except.push_back(_word); | ||
| 125 | |||
| 126 | return *this; | ||
| 127 | } | ||
| 128 | |||
| 129 | noun_query& noun_query::rhymes_with(const word& _word) | ||
| 130 | { | ||
| 131 | for (auto rhyme : _word.rhyme_phonemes()) | ||
| 132 | { | ||
| 133 | _rhymes.push_back(rhyme); | ||
| 134 | } | ||
| 135 | |||
| 136 | if (dynamic_cast<const noun*>(&_word) != nullptr) | ||
| 137 | { | ||
| 138 | _except.push_back(dynamic_cast<const noun&>(_word)); | ||
| 139 | } | ||
| 140 | |||
| 141 | return *this; | ||
| 142 | } | ||
| 143 | |||
| 144 | noun_query& noun_query::has_pronunciation(bool _has_prn) | ||
| 145 | { | ||
| 146 | this->_has_prn = _has_prn; | ||
| 147 | |||
| 148 | return *this; | ||
| 149 | } | ||
| 150 | |||
| 151 | noun_query& noun_query::is_hypernym(bool _arg) | ||
| 152 | { | ||
| 153 | _is_hypernym = _arg; | ||
| 154 | |||
| 155 | return *this; | ||
| 156 | } | ||
| 157 | |||
| 158 | noun_query& noun_query::hypernym_of(const noun& _noun) | ||
| 159 | { | ||
| 160 | _hypernym_of.push_back(_noun); | ||
| 161 | |||
| 162 | return *this; | ||
| 163 | } | ||
| 164 | |||
| 165 | noun_query& noun_query::not_hypernym_of(const noun& _noun) | ||
| 166 | { | ||
| 167 | _not_hypernym_of.push_back(_noun); | ||
| 168 | |||
| 169 | return *this; | ||
| 170 | } | ||
| 171 | |||
| 172 | noun_query& noun_query::is_hyponym(bool _arg) | ||
| 173 | { | ||
| 174 | _is_hyponym = _arg; | ||
| 175 | |||
| 176 | return *this; | ||
| 177 | } | ||
| 178 | |||
| 179 | noun_query& noun_query::hyponym_of(const noun& _noun) | ||
| 180 | { | ||
| 181 | _hyponym_of.push_back(_noun); | ||
| 182 | |||
| 183 | return *this; | ||
| 184 | } | ||
| 185 | |||
| 186 | noun_query& noun_query::not_hyponym_of(const noun& _noun) | ||
| 187 | { | ||
| 188 | _not_hyponym_of.push_back(_noun); | ||
| 189 | |||
| 190 | return *this; | ||
| 191 | } | ||
| 192 | |||
| 193 | noun_query& noun_query::is_part_meronym(bool _arg) | ||
| 194 | { | ||
| 195 | _is_part_meronym = _arg; | ||
| 196 | |||
| 197 | return *this; | ||
| 198 | } | ||
| 199 | |||
| 200 | noun_query& noun_query::part_meronym_of(const noun& _noun) | ||
| 201 | { | ||
| 202 | _part_meronym_of.push_back(_noun); | ||
| 203 | 48 | ||
| 204 | return *this; | 49 | return _data->nouns().hypernym_of(*this); |
| 205 | } | 50 | } |
| 206 | 51 | ||
| 207 | noun_query& noun_query::not_part_meronym_of(const noun& _noun) | 52 | noun_query noun::full_hypernyms() const |
| 208 | { | 53 | { |
| 209 | _not_part_meronym_of.push_back(_noun); | 54 | assert(_valid == true); |
| 210 | 55 | ||
| 211 | return *this; | 56 | return _data->nouns().full_hypernym_of(*this); |
| 212 | } | 57 | } |
| 213 | 58 | ||
| 214 | noun_query& noun_query::is_part_holonym(bool _arg) | 59 | noun_query noun::hyponyms() const |
| 215 | { | ||
| 216 | _is_part_holonym = _arg; | ||
| 217 | |||
| 218 | return *this; | ||
| 219 | } | ||
| 220 | |||
| 221 | noun_query& noun_query::part_holonym_of(const noun& _noun) | ||
| 222 | { | ||
| 223 | _part_holonym_of.push_back(_noun); | ||
| 224 | |||
| 225 | return *this; | ||
| 226 | } | ||
| 227 | |||
| 228 | noun_query& noun_query::not_part_holonym_of(const noun& _noun) | ||
| 229 | { | ||
| 230 | _not_part_holonym_of.push_back(_noun); | ||
| 231 | |||
| 232 | return *this; | ||
| 233 | } | ||
| 234 | |||
| 235 | noun_query& noun_query::is_substance_meronym(bool _arg) | ||
| 236 | { | ||
| 237 | _is_substance_meronym = _arg; | ||
| 238 | |||
| 239 | return *this; | ||
| 240 | } | ||
| 241 | |||
| 242 | noun_query& noun_query::substance_meronym_of(const noun& _noun) | ||
| 243 | { | ||
| 244 | _substance_meronym_of.push_back(_noun); | ||
| 245 | |||
| 246 | return *this; | ||
| 247 | } | ||
| 248 | |||
| 249 | noun_query& noun_query::not_substance_meronym_of(const noun& _noun) | ||
| 250 | { | ||
| 251 | _not_substance_meronym_of.push_back(_noun); | ||
| 252 | |||
| 253 | return *this; | ||
| 254 | } | ||
| 255 | |||
| 256 | noun_query& noun_query::is_substance_holonym(bool _arg) | ||
| 257 | { | ||
| 258 | _is_substance_holonym = _arg; | ||
| 259 | |||
| 260 | return *this; | ||
| 261 | } | ||
| 262 | |||
| 263 | noun_query& noun_query::substance_holonym_of(const noun& _noun) | ||
| 264 | { | ||
| 265 | _substance_holonym_of.push_back(_noun); | ||
| 266 | |||
| 267 | return *this; | ||
| 268 | } | ||
| 269 | |||
| 270 | noun_query& noun_query::not_substance_holonym_of(const noun& _noun) | ||
| 271 | { | ||
| 272 | _not_substance_holonym_of.push_back(_noun); | ||
| 273 | |||
| 274 | return *this; | ||
| 275 | } | ||
| 276 | |||
| 277 | noun_query& noun_query::is_member_meronym(bool _arg) | ||
| 278 | { | ||
| 279 | _is_member_meronym = _arg; | ||
| 280 | |||
| 281 | return *this; | ||
| 282 | } | ||
| 283 | |||
| 284 | noun_query& noun_query::member_meronym_of(const noun& _noun) | ||
| 285 | { | ||
| 286 | _member_meronym_of.push_back(_noun); | ||
| 287 | |||
| 288 | return *this; | ||
| 289 | } | ||
| 290 | |||
| 291 | noun_query& noun_query::not_member_meronym_of(const noun& _noun) | ||
| 292 | { | ||
| 293 | _not_member_meronym_of.push_back(_noun); | ||
| 294 | |||
| 295 | return *this; | ||
| 296 | } | ||
| 297 | |||
| 298 | noun_query& noun_query::is_member_holonym(bool _arg) | ||
| 299 | { | ||
| 300 | _is_member_holonym = _arg; | ||
| 301 | |||
| 302 | return *this; | ||
| 303 | } | ||
| 304 | |||
| 305 | noun_query& noun_query::member_holonym_of(const noun& _noun) | ||
| 306 | { | ||
| 307 | _member_holonym_of.push_back(_noun); | ||
| 308 | |||
| 309 | return *this; | ||
| 310 | } | ||
| 311 | |||
| 312 | noun_query& noun_query::not_member_holonym_of(const noun& _noun) | ||
| 313 | { | ||
| 314 | _not_member_holonym_of.push_back(_noun); | ||
| 315 | |||
| 316 | return *this; | ||
| 317 | } | ||
| 318 | |||
| 319 | noun_query& noun_query::is_proper(bool _arg) | ||
| 320 | { | ||
| 321 | _is_proper = _arg; | ||
| 322 | |||
| 323 | return *this; | ||
| 324 | } | ||
| 325 | |||
| 326 | noun_query& noun_query::is_not_proper(bool _arg) | ||
| 327 | { | ||
| 328 | _is_not_proper = _arg; | ||
| 329 | |||
| 330 | return *this; | ||
| 331 | } | ||
| 332 | |||
| 333 | noun_query& noun_query::is_instance(bool _arg) | ||
| 334 | { | ||
| 335 | _is_instance = _arg; | ||
| 336 | |||
| 337 | return *this; | ||
| 338 | } | ||
| 339 | |||
| 340 | noun_query& noun_query::instance_of(const noun& _noun) | ||
| 341 | { | ||
| 342 | _instance_of.push_back(_noun); | ||
| 343 | |||
| 344 | return *this; | ||
| 345 | } | ||
| 346 | |||
| 347 | noun_query& noun_query::not_instance_of(const noun& _noun) | ||
| 348 | { | ||
| 349 | _not_instance_of.push_back(_noun); | ||
| 350 | |||
| 351 | return *this; | ||
| 352 | } | ||
| 353 | |||
| 354 | noun_query& noun_query::is_class(bool _arg) | ||
| 355 | { | ||
| 356 | _is_class = _arg; | ||
| 357 | |||
| 358 | return *this; | ||
| 359 | } | ||
| 360 | |||
| 361 | noun_query& noun_query::class_of(const noun& _noun) | ||
| 362 | { | 60 | { |
| 363 | _class_of.push_back(_noun); | 61 | assert(_valid == true); |
| 364 | 62 | ||
| 365 | return *this; | 63 | return _data->nouns().hyponym_of(*this); |
| 366 | } | 64 | } |
| 367 | 65 | ||
| 368 | noun_query& noun_query::not_class_of(const noun& _noun) | 66 | noun_query noun::full_hyponyms() const |
| 369 | { | 67 | { |
| 370 | _not_class_of.push_back(_noun); | 68 | assert(_valid == true); |
| 371 | 69 | ||
| 372 | return *this; | 70 | return _data->nouns().full_hyponym_of(*this); |
| 373 | } | 71 | } |
| 374 | 72 | ||
| 375 | noun_query& noun_query::has_synonyms(bool _arg) | 73 | noun_query noun::part_meronyms() const |
| 376 | { | 74 | { |
| 377 | _has_synonyms = _arg; | 75 | assert(_valid == true); |
| 378 | 76 | ||
| 379 | return *this; | 77 | return _data->nouns().part_meronym_of(*this); |
| 380 | } | 78 | } |
| 381 | 79 | ||
| 382 | noun_query& noun_query::synonym_of(const noun& _noun) | 80 | noun_query noun::part_holonyms() const |
| 383 | { | 81 | { |
| 384 | _synonym_of.push_back(_noun); | 82 | assert(_valid == true); |
| 385 | 83 | ||
| 386 | return *this; | 84 | return _data->nouns().part_holonym_of(*this); |
| 387 | } | 85 | } |
| 388 | 86 | ||
| 389 | noun_query& noun_query::not_synonym_of(const noun& _noun) | 87 | noun_query noun::substance_meronyms() const |
| 390 | { | 88 | { |
| 391 | _not_synonym_of.push_back(_noun); | 89 | assert(_valid == true); |
| 392 | 90 | ||
| 393 | return *this; | 91 | return _data->nouns().substance_meronym_of(*this); |
| 394 | } | 92 | } |
| 395 | 93 | ||
| 396 | noun_query& noun_query::has_antonyms(bool _arg) | 94 | noun_query noun::substance_holonyms() const |
| 397 | { | 95 | { |
| 398 | _has_antonyms = _arg; | 96 | assert(_valid == true); |
| 399 | 97 | ||
| 400 | return *this; | 98 | return _data->nouns().substance_holonym_of(*this); |
| 401 | } | 99 | } |
| 402 | 100 | ||
| 403 | noun_query& noun_query::antonym_of(const noun& _noun) | 101 | noun_query noun::member_meronyms() const |
| 404 | { | 102 | { |
| 405 | _antonym_of.push_back(_noun); | 103 | assert(_valid == true); |
| 406 | 104 | ||
| 407 | return *this; | 105 | return _data->nouns().member_meronym_of(*this); |
| 408 | } | 106 | } |
| 409 | 107 | ||
| 410 | noun_query& noun_query::not_antonym_of(const noun& _noun) | 108 | noun_query noun::member_holonyms() const |
| 411 | { | 109 | { |
| 412 | _not_antonym_of.push_back(_noun); | 110 | assert(_valid == true); |
| 413 | 111 | ||
| 414 | return *this; | 112 | return _data->nouns().member_holonym_of(*this); |
| 415 | } | 113 | } |
| 416 | 114 | ||
| 417 | noun_query& noun_query::has_pertainym(bool _arg) | 115 | noun_query noun::classes() const |
| 418 | { | 116 | { |
| 419 | _has_pertainym = _arg; | 117 | assert(_valid == true); |
| 420 | 118 | ||
| 421 | return *this; | 119 | return _data->nouns().class_of(*this); |
| 422 | } | 120 | } |
| 423 | 121 | ||
| 424 | noun_query& noun_query::anti_pertainym_of(const adjective& _adj) | 122 | noun_query noun::instances() const |
| 425 | { | 123 | { |
| 426 | _anti_pertainym_of.push_back(_adj); | 124 | assert(_valid == true); |
| 427 | 125 | ||
| 428 | return *this; | 126 | return _data->nouns().instance_of(*this); |
| 429 | } | 127 | } |
| 430 | 128 | ||
| 431 | noun_query& noun_query::is_attribute(bool _arg) | 129 | noun_query noun::synonyms() const |
| 432 | { | 130 | { |
| 433 | _is_attribute = _arg; | 131 | assert(_valid == true); |
| 434 | 132 | ||
| 435 | return *this; | 133 | return _data->nouns().synonym_of(*this); |
| 436 | } | 134 | } |
| 437 | 135 | ||
| 438 | noun_query& noun_query::attribute_of(const adjective& _adj) | 136 | noun_query noun::antonyms() const |
| 439 | { | 137 | { |
| 440 | _attribute_of.push_back(_adj); | 138 | assert(_valid == true); |
| 441 | 139 | ||
| 442 | return *this; | 140 | return _data->nouns().antonym_of(*this); |
| 443 | } | 141 | } |
| 444 | 142 | ||
| 445 | noun_query& noun_query::derived_from(const word& _w) | 143 | adjective_query noun::pertainyms() const |
| 446 | { | 144 | { |
| 447 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 145 | assert(_valid == true); |
| 448 | { | ||
| 449 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 450 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 451 | { | ||
| 452 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 453 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 454 | { | ||
| 455 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 456 | } | ||
| 457 | 146 | ||
| 458 | return *this; | 147 | return _data->adjectives().pertainym_of(*this); |
| 459 | } | 148 | } |
| 460 | 149 | ||
| 461 | noun_query& noun_query::not_derived_from(const word& _w) | 150 | adjective_query noun::variations() const |
| 462 | { | 151 | { |
| 463 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 152 | assert(_valid == true); |
| 464 | { | ||
| 465 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 466 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 467 | { | ||
| 468 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 469 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 470 | { | ||
| 471 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 472 | } | ||
| 473 | 153 | ||
| 474 | return *this; | 154 | return _data->adjectives().variant_of(*this); |
| 475 | } | 155 | } |
| 476 | 156 | ||
| 477 | std::list<noun> noun_query::run() const | 157 | bool noun::operator<(const noun& other) const |
| 478 | { | 158 | { |
| 479 | std::stringstream construct; | 159 | return _id < other._id; |
| 480 | construct << "SELECT noun_id, singular, plural FROM nouns"; | ||
| 481 | std::list<std::string> conditions; | ||
| 482 | |||
| 483 | if (_has_prn) | ||
| 484 | { | ||
| 485 | conditions.push_back("noun_id IN (SELECT noun_id FROM noun_pronunciations)"); | ||
| 486 | } | ||
| 487 | |||
| 488 | if (!_rhymes.empty()) | ||
| 489 | { | ||
| 490 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
| 491 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 492 | conditions.push_back(cond); | ||
| 493 | } | ||
| 494 | |||
| 495 | for (auto except : _except) | ||
| 496 | { | ||
| 497 | conditions.push_back("noun_id != @EXCID"); | ||
| 498 | } | ||
| 499 | |||
| 500 | if (_is_hypernym) | ||
| 501 | { | ||
| 502 | conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)"); | ||
| 503 | } | ||
| 504 | |||
| 505 | if (!_hypernym_of.empty()) | ||
| 506 | { | ||
| 507 | std::list<std::string> clauses(_hypernym_of.size(), "hyponym_id = @HYPO"); | ||
| 508 | std::string cond = "noun_id IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 509 | conditions.push_back(cond); | ||
| 510 | } | ||
| 511 | |||
| 512 | if (!_not_hypernym_of.empty()) | ||
| 513 | { | ||
| 514 | std::list<std::string> clauses(_not_hypernym_of.size(), "hyponym_id = @NHYPO"); | ||
| 515 | std::string cond = "noun_id NOT IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 516 | conditions.push_back(cond); | ||
| 517 | } | ||
| 518 | |||
| 519 | if (_is_hyponym) | ||
| 520 | { | ||
| 521 | conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)"); | ||
| 522 | } | ||
| 523 | |||
| 524 | if (!_hyponym_of.empty()) | ||
| 525 | { | ||
| 526 | std::list<std::string> clauses(_hyponym_of.size(), "hypernym_id = @HYPER"); | ||
| 527 | std::string cond = "noun_id IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 528 | conditions.push_back(cond); | ||
| 529 | } | ||
| 530 | |||
| 531 | if (!_not_hyponym_of.empty()) | ||
| 532 | { | ||
| 533 | std::list<std::string> clauses(_not_hyponym_of.size(), "hypernym_id = @NHYPER"); | ||
| 534 | std::string cond = "noun_id NOT IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 535 | conditions.push_back(cond); | ||
| 536 | } | ||
| 537 | |||
| 538 | if (_is_part_meronym) | ||
| 539 | { | ||
| 540 | conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)"); | ||
| 541 | } | ||
| 542 | |||
| 543 | if (!_part_meronym_of.empty()) | ||
| 544 | { | ||
| 545 | std::list<std::string> clauses(_part_meronym_of.size(), "holonym_id = @PHOLO"); | ||
| 546 | std::string cond = "noun_id IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 547 | conditions.push_back(cond); | ||
| 548 | } | ||
| 549 | |||
| 550 | if (!_not_part_meronym_of.empty()) | ||
| 551 | { | ||
| 552 | std::list<std::string> clauses(_not_part_meronym_of.size(), "holonym_id = @NPHOLO"); | ||
| 553 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 554 | conditions.push_back(cond); | ||
| 555 | } | ||
| 556 | |||
| 557 | if (_is_part_holonym) | ||
| 558 | { | ||
| 559 | conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)"); | ||
| 560 | } | ||
| 561 | |||
| 562 | if (!_part_holonym_of.empty()) | ||
| 563 | { | ||
| 564 | std::list<std::string> clauses(_part_holonym_of.size(), "meronym_id = @PMERO"); | ||
| 565 | std::string cond = "noun_id IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 566 | conditions.push_back(cond); | ||
| 567 | } | ||
| 568 | |||
| 569 | if (!_not_part_holonym_of.empty()) | ||
| 570 | { | ||
| 571 | std::list<std::string> clauses(_not_part_holonym_of.size(), "meronym_id = @NPMERO"); | ||
| 572 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 573 | conditions.push_back(cond); | ||
| 574 | } | ||
| 575 | |||
| 576 | if (_is_substance_meronym) | ||
| 577 | { | ||
| 578 | conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)"); | ||
| 579 | } | ||
| 580 | |||
| 581 | if (!_substance_meronym_of.empty()) | ||
| 582 | { | ||
| 583 | std::list<std::string> clauses(_substance_meronym_of.size(), "holonym_id = @SHOLO"); | ||
| 584 | std::string cond = "noun_id IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 585 | conditions.push_back(cond); | ||
| 586 | } | ||
| 587 | |||
| 588 | if (!_not_substance_meronym_of.empty()) | ||
| 589 | { | ||
| 590 | std::list<std::string> clauses(_not_substance_meronym_of.size(), "holonym_id = @NSHOLO"); | ||
| 591 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 592 | conditions.push_back(cond); | ||
| 593 | } | ||
| 594 | |||
| 595 | if (_is_substance_holonym) | ||
| 596 | { | ||
| 597 | conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)"); | ||
| 598 | } | ||
| 599 | |||
| 600 | if (!_substance_holonym_of.empty()) | ||
| 601 | { | ||
| 602 | std::list<std::string> clauses(_substance_holonym_of.size(), "meronym_id = @SMERO"); | ||
| 603 | std::string cond = "noun_id IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 604 | conditions.push_back(cond); | ||
| 605 | } | ||
| 606 | |||
| 607 | if (!_not_substance_holonym_of.empty()) | ||
| 608 | { | ||
| 609 | std::list<std::string> clauses(_not_substance_holonym_of.size(), "meronym_id = @NSMERO"); | ||
| 610 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 611 | conditions.push_back(cond); | ||
| 612 | } | ||
| 613 | |||
| 614 | if (_is_member_meronym) | ||
| 615 | { | ||
| 616 | conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)"); | ||
| 617 | } | ||
| 618 | |||
| 619 | if (!_member_meronym_of.empty()) | ||
| 620 | { | ||
| 621 | std::list<std::string> clauses(_member_meronym_of.size(), "holonym_id = @MHOLO"); | ||
| 622 | std::string cond = "noun_id IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 623 | conditions.push_back(cond); | ||
| 624 | } | ||
| 625 | |||
| 626 | if (!_not_member_meronym_of.empty()) | ||
| 627 | { | ||
| 628 | std::list<std::string> clauses(_not_member_meronym_of.size(), "holonym_id = @NMHOLO"); | ||
| 629 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 630 | conditions.push_back(cond); | ||
| 631 | } | ||
| 632 | |||
| 633 | if (_is_member_holonym) | ||
| 634 | { | ||
| 635 | conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)"); | ||
| 636 | } | ||
| 637 | |||
| 638 | if (!_member_holonym_of.empty()) | ||
| 639 | { | ||
| 640 | std::list<std::string> clauses(_member_holonym_of.size(), "meronym_id = @MMERO"); | ||
| 641 | std::string cond = "noun_id IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 642 | conditions.push_back(cond); | ||
| 643 | } | ||
| 644 | |||
| 645 | if (!_not_member_holonym_of.empty()) | ||
| 646 | { | ||
| 647 | std::list<std::string> clauses(_not_member_holonym_of.size(), "meronym_id = @NMMERO"); | ||
| 648 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 649 | conditions.push_back(cond); | ||
| 650 | } | ||
| 651 | |||
| 652 | if (_is_proper) | ||
| 653 | { | ||
| 654 | conditions.push_back("proper = 1"); | ||
| 655 | } | ||
| 656 | |||
| 657 | if (_is_not_proper) | ||
| 658 | { | ||
| 659 | conditions.push_back("proper = 0"); | ||
| 660 | } | ||
| 661 | |||
| 662 | if (_is_instance) | ||
| 663 | { | ||
| 664 | conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)"); | ||
| 665 | } | ||
| 666 | |||
| 667 | if (!_instance_of.empty()) | ||
| 668 | { | ||
| 669 | std::list<std::string> clauses(_instance_of.size(), "class_id = @CLSID"); | ||
| 670 | std::string cond = "noun_id IN (SELECT instance_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 671 | conditions.push_back(cond); | ||
| 672 | } | ||
| 673 | |||
| 674 | if (!_not_instance_of.empty()) | ||
| 675 | { | ||
| 676 | std::list<std::string> clauses(_not_instance_of.size(), "class_id = @NCLSID"); | ||
| 677 | std::string cond = "noun_id NOT IN (SELECT instance_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 678 | conditions.push_back(cond); | ||
| 679 | } | ||
| 680 | |||
| 681 | if (_is_class) | ||
| 682 | { | ||
| 683 | conditions.push_back("noun_id IN (SELECT class_id FROM instantiation)"); | ||
| 684 | } | ||
| 685 | |||
| 686 | if (!_class_of.empty()) | ||
| 687 | { | ||
| 688 | std::list<std::string> clauses(_class_of.size(), "instance_id = @INSID"); | ||
| 689 | std::string cond = "noun_id IN (SELECT class_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 690 | conditions.push_back(cond); | ||
| 691 | } | ||
| 692 | |||
| 693 | if (!_not_class_of.empty()) | ||
| 694 | { | ||
| 695 | std::list<std::string> clauses(_not_class_of.size(), "instance_id = @NINSID"); | ||
| 696 | std::string cond = "noun_id NOT IN (SELECT class_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 697 | conditions.push_back(cond); | ||
| 698 | } | ||
| 699 | |||
| 700 | if (_has_synonyms) | ||
| 701 | { | ||
| 702 | conditions.push_back("noun_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); | ||
| 703 | } | ||
| 704 | |||
| 705 | if (!_synonym_of.empty()) | ||
| 706 | { | ||
| 707 | std::list<std::string> clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); | ||
| 708 | std::string cond = "noun_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 709 | conditions.push_back(cond); | ||
| 710 | } | ||
| 711 | |||
| 712 | if (!_not_synonym_of.empty()) | ||
| 713 | { | ||
| 714 | std::list<std::string> clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); | ||
| 715 | std::string cond = "noun_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 716 | conditions.push_back(cond); | ||
| 717 | } | ||
| 718 | |||
| 719 | if (_has_antonyms) | ||
| 720 | { | ||
| 721 | conditions.push_back("noun_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); | ||
| 722 | } | ||
| 723 | |||
| 724 | if (!_antonym_of.empty()) | ||
| 725 | { | ||
| 726 | std::list<std::string> clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); | ||
| 727 | std::string cond = "noun_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 728 | conditions.push_back(cond); | ||
| 729 | } | ||
| 730 | |||
| 731 | if (!_not_antonym_of.empty()) | ||
| 732 | { | ||
| 733 | std::list<std::string> clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); | ||
| 734 | std::string cond = "noun_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 735 | conditions.push_back(cond); | ||
| 736 | } | ||
| 737 | |||
| 738 | if (_has_pertainym) | ||
| 739 | { | ||
| 740 | conditions.push_back("noun_id IN (SELECT noun_id FROM pertainymy)"); | ||
| 741 | } | ||
| 742 | |||
| 743 | if (!_anti_pertainym_of.empty()) | ||
| 744 | { | ||
| 745 | std::list<std::string> clauses(_anti_pertainym_of.size(), "pertainym_id = @PERID"); | ||
| 746 | std::string cond = "noun_id IN (SELECT noun_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 747 | conditions.push_back(cond); | ||
| 748 | } | ||
| 749 | |||
| 750 | if (_is_attribute) | ||
| 751 | { | ||
| 752 | conditions.push_back("noun_id IN (SELECT noun_id FROM variation)"); | ||
| 753 | } | ||
| 754 | |||
| 755 | if (!_attribute_of.empty()) | ||
| 756 | { | ||
| 757 | std::list<std::string> clauses(_attribute_of.size(), "adjective_id = @VALID"); | ||
| 758 | std::string cond = "noun_id IN (SELECT noun_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 759 | conditions.push_back(cond); | ||
| 760 | } | ||
| 761 | |||
| 762 | if (!_derived_from_adjective.empty()) | ||
| 763 | { | ||
| 764 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); | ||
| 765 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 766 | conditions.push_back(cond); | ||
| 767 | } | ||
| 768 | |||
| 769 | if (!_not_derived_from_adjective.empty()) | ||
| 770 | { | ||
| 771 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); | ||
| 772 | std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 773 | conditions.push_back(cond); | ||
| 774 | } | ||
| 775 | |||
| 776 | if (!_derived_from_adverb.empty()) | ||
| 777 | { | ||
| 778 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); | ||
| 779 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 780 | conditions.push_back(cond); | ||
| 781 | } | ||
| 782 | |||
| 783 | if (!_not_derived_from_adverb.empty()) | ||
| 784 | { | ||
| 785 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); | ||
| 786 | std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 787 | conditions.push_back(cond); | ||
| 788 | } | ||
| 789 | |||
| 790 | if (!_derived_from_noun.empty()) | ||
| 791 | { | ||
| 792 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_2_id = @DERN"); | ||
| 793 | std::string cond = "noun_id IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 794 | conditions.push_back(cond); | ||
| 795 | } | ||
| 796 | |||
| 797 | if (!_not_derived_from_noun.empty()) | ||
| 798 | { | ||
| 799 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_2_id = @NDERN"); | ||
| 800 | 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 ") + ")"; | ||
| 801 | conditions.push_back(cond); | ||
| 802 | } | ||
| 803 | |||
| 804 | if (!conditions.empty()) | ||
| 805 | { | ||
| 806 | construct << " WHERE "; | ||
| 807 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
| 808 | } | ||
| 809 | |||
| 810 | if (_random) | ||
| 811 | { | ||
| 812 | construct << " ORDER BY RANDOM()"; | ||
| 813 | } | ||
| 814 | |||
| 815 | if (_limit != unlimited) | ||
| 816 | { | ||
| 817 | construct << " LIMIT " << _limit; | ||
| 818 | } | ||
| 819 | |||
| 820 | sqlite3_stmt* ppstmt; | ||
| 821 | std::string query = construct.str(); | ||
| 822 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 823 | { | ||
| 824 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 825 | } | ||
| 826 | |||
| 827 | if (!_rhymes.empty()) | ||
| 828 | { | ||
| 829 | int i = 0; | ||
| 830 | for (auto rhyme : _rhymes) | ||
| 831 | { | ||
| 832 | std::string rhymer = "%" + rhyme; | ||
| 833 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
| 834 | |||
| 835 | i++; | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | for (auto except : _except) | ||
| 840 | { | ||
| 841 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
| 842 | } | ||
| 843 | |||
| 844 | for (auto hyponym : _hypernym_of) | ||
| 845 | { | ||
| 846 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPO"), hyponym._id); | ||
| 847 | } | ||
| 848 | |||
| 849 | for (auto hyponym : _not_hypernym_of) | ||
| 850 | { | ||
| 851 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NHYPO"), hyponym._id); | ||
| 852 | } | ||
| 853 | |||
| 854 | for (auto hypernym : _hyponym_of) | ||
| 855 | { | ||
| 856 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPER"), hypernym._id); | ||
| 857 | } | ||
| 858 | |||
| 859 | for (auto hypernym : _not_hyponym_of) | ||
| 860 | { | ||
| 861 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NHYPER"), hypernym._id); | ||
| 862 | } | ||
| 863 | |||
| 864 | for (auto holonym : _part_meronym_of) | ||
| 865 | { | ||
| 866 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PHOLO"), holonym._id); | ||
| 867 | } | ||
| 868 | |||
| 869 | for (auto holonym : _not_part_meronym_of) | ||
| 870 | { | ||
| 871 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NPHOLO"), holonym._id); | ||
| 872 | } | ||
| 873 | |||
| 874 | for (auto meronym : _part_holonym_of) | ||
| 875 | { | ||
| 876 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PMERO"), meronym._id); | ||
| 877 | } | ||
| 878 | |||
| 879 | for (auto meronym : _not_part_holonym_of) | ||
| 880 | { | ||
| 881 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NPMERO"), meronym._id); | ||
| 882 | } | ||
| 883 | |||
| 884 | for (auto holonym : _substance_meronym_of) | ||
| 885 | { | ||
| 886 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SHOLO"), holonym._id); | ||
| 887 | } | ||
| 888 | |||
| 889 | for (auto holonym : _not_substance_meronym_of) | ||
| 890 | { | ||
| 891 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSHOLO"), holonym._id); | ||
| 892 | } | ||
| 893 | |||
| 894 | for (auto meronym : _substance_holonym_of) | ||
| 895 | { | ||
| 896 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SMERO"), meronym._id); | ||
| 897 | } | ||
| 898 | |||
| 899 | for (auto meronym : _not_substance_holonym_of) | ||
| 900 | { | ||
| 901 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSMERO"), meronym._id); | ||
| 902 | } | ||
| 903 | |||
| 904 | for (auto holonym : _member_meronym_of) | ||
| 905 | { | ||
| 906 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MHOLO"), holonym._id); | ||
| 907 | } | ||
| 908 | |||
| 909 | for (auto holonym : _not_member_meronym_of) | ||
| 910 | { | ||
| 911 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NMHOLO"), holonym._id); | ||
| 912 | } | ||
| 913 | |||
| 914 | for (auto meronym : _member_holonym_of) | ||
| 915 | { | ||
| 916 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MMERO"), meronym._id); | ||
| 917 | } | ||
| 918 | |||
| 919 | for (auto meronym : _not_member_holonym_of) | ||
| 920 | { | ||
| 921 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NMMERO"), meronym._id); | ||
| 922 | } | ||
| 923 | |||
| 924 | for (auto cls : _instance_of) | ||
| 925 | { | ||
| 926 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@CLSID"), cls._id); | ||
| 927 | } | ||
| 928 | |||
| 929 | for (auto cls : _not_instance_of) | ||
| 930 | { | ||
| 931 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NCLSID"), cls._id); | ||
| 932 | } | ||
| 933 | |||
| 934 | for (auto inst : _class_of) | ||
| 935 | { | ||
| 936 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@INSID"), inst._id); | ||
| 937 | } | ||
| 938 | |||
| 939 | for (auto inst : _not_class_of) | ||
| 940 | { | ||
| 941 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NINSID"), inst._id); | ||
| 942 | } | ||
| 943 | |||
| 944 | for (auto synonym : _synonym_of) | ||
| 945 | { | ||
| 946 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
| 947 | } | ||
| 948 | |||
| 949 | for (auto synonym : _not_synonym_of) | ||
| 950 | { | ||
| 951 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
| 952 | } | ||
| 953 | |||
| 954 | for (auto antonym : _antonym_of) | ||
| 955 | { | ||
| 956 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
| 957 | } | ||
| 958 | |||
| 959 | for (auto antonym : _not_antonym_of) | ||
| 960 | { | ||
| 961 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
| 962 | } | ||
| 963 | |||
| 964 | for (auto pertainym : _anti_pertainym_of) | ||
| 965 | { | ||
| 966 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PERID"), pertainym._id); | ||
| 967 | } | ||
| 968 | |||
| 969 | for (auto value : _attribute_of) | ||
| 970 | { | ||
| 971 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VALID"), value._id); | ||
| 972 | } | ||
| 973 | |||
| 974 | for (auto adj : _derived_from_adjective) | ||
| 975 | { | ||
| 976 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
| 977 | } | ||
| 978 | |||
| 979 | for (auto adj : _not_derived_from_adjective) | ||
| 980 | { | ||
| 981 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
| 982 | } | ||
| 983 | |||
| 984 | for (auto adv : _derived_from_adverb) | ||
| 985 | { | ||
| 986 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
| 987 | } | ||
| 988 | |||
| 989 | for (auto adv : _not_derived_from_adverb) | ||
| 990 | { | ||
| 991 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
| 992 | } | ||
| 993 | |||
| 994 | for (auto n : _derived_from_noun) | ||
| 995 | { | ||
| 996 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
| 997 | } | ||
| 998 | |||
| 999 | for (auto n : _not_derived_from_noun) | ||
| 1000 | { | ||
| 1001 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | std::list<noun> output; | ||
| 1005 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 1006 | { | ||
| 1007 | noun tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
| 1008 | tnc._singular = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
| 1009 | |||
| 1010 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
| 1011 | { | ||
| 1012 | tnc._plural = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | output.push_back(tnc); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | sqlite3_finalize(ppstmt); | ||
| 1019 | |||
| 1020 | for (auto& noun : output) | ||
| 1021 | { | ||
| 1022 | query = "SELECT pronunciation FROM noun_pronunciations WHERE noun_id = ?"; | ||
| 1023 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 1024 | { | ||
| 1025 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | sqlite3_bind_int(ppstmt, 1, noun._id); | ||
| 1029 | |||
| 1030 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 1031 | { | ||
| 1032 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 1033 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
| 1034 | |||
| 1035 | noun.pronunciations.push_back(phonemes); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | sqlite3_finalize(ppstmt); | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | return output; | ||
| 1042 | } | 160 | } |
| 1043 | 161 | ||
| 1044 | }; | 162 | }; |
| 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 { | |||
| 11 | friend class noun_query; | 11 | friend class noun_query; |
| 12 | 12 | ||
| 13 | public: | 13 | public: |
| 14 | noun(); | ||
| 14 | noun(const data& _data, int _id); | 15 | noun(const data& _data, int _id); |
| 15 | 16 | ||
| 16 | std::string base_form() const; | 17 | std::string base_form() const; |
| @@ -20,7 +21,9 @@ namespace verbly { | |||
| 20 | bool has_plural_form() const; | 21 | bool has_plural_form() const; |
| 21 | 22 | ||
| 22 | noun_query hypernyms() const; | 23 | noun_query hypernyms() const; |
| 24 | noun_query full_hypernyms() const; | ||
| 23 | noun_query hyponyms() const; | 25 | noun_query hyponyms() const; |
| 26 | noun_query full_hyponyms() const; | ||
| 24 | noun_query part_meronyms() const; | 27 | noun_query part_meronyms() const; |
| 25 | noun_query part_holonyms() const; | 28 | noun_query part_holonyms() const; |
| 26 | noun_query substance_meronyms() const; | 29 | noun_query substance_meronyms() const; |
| @@ -33,153 +36,8 @@ namespace verbly { | |||
| 33 | noun_query antonyms() const; | 36 | noun_query antonyms() const; |
| 34 | adjective_query pertainyms() const; | 37 | adjective_query pertainyms() const; |
| 35 | adjective_query variations() const; | 38 | adjective_query variations() const; |
| 36 | }; | ||
| 37 | |||
| 38 | class noun_query { | ||
| 39 | public: | ||
| 40 | noun_query(const data& _data); | ||
| 41 | |||
| 42 | noun_query& limit(int _limit); | ||
| 43 | noun_query& random(bool _random); | ||
| 44 | noun_query& except(const noun& _word); | ||
| 45 | noun_query& rhymes_with(const word& _word); | ||
| 46 | noun_query& has_pronunciation(bool _has_prn); | ||
| 47 | |||
| 48 | noun_query& is_hypernym(bool _arg); | ||
| 49 | noun_query& hypernym_of(const noun& _noun); | ||
| 50 | noun_query& not_hypernym_of(const noun& _noun); | ||
| 51 | |||
| 52 | noun_query& is_hyponym(bool _arg); | ||
| 53 | noun_query& hyponym_of(const noun& _noun); | ||
| 54 | noun_query& not_hyponym_of(const noun& _noun); | ||
| 55 | |||
| 56 | noun_query& is_part_meronym(bool _arg); | ||
| 57 | noun_query& part_meronym_of(const noun& _noun); | ||
| 58 | noun_query& not_part_meronym_of(const noun& _noun); | ||
| 59 | |||
| 60 | noun_query& is_part_holonym(bool _arg); | ||
| 61 | noun_query& part_holonym_of(const noun& _noun); | ||
| 62 | noun_query& not_part_holonym_of(const noun& _noun); | ||
| 63 | |||
| 64 | noun_query& is_substance_meronym(bool _arg); | ||
| 65 | noun_query& substance_meronym_of(const noun& _noun); | ||
| 66 | noun_query& not_substance_meronym_of(const noun& _noun); | ||
| 67 | |||
| 68 | noun_query& is_substance_holonym(bool _arg); | ||
| 69 | noun_query& substance_holonym_of(const noun& _noun); | ||
| 70 | noun_query& not_substance_holonym_of(const noun& _noun); | ||
| 71 | |||
| 72 | noun_query& is_member_meronym(bool _arg); | ||
| 73 | noun_query& member_meronym_of(const noun& _noun); | ||
| 74 | noun_query& not_member_meronym_of(const noun& _noun); | ||
| 75 | |||
| 76 | noun_query& is_member_holonym(bool _arg); | ||
| 77 | noun_query& member_holonym_of(const noun& _noun); | ||
| 78 | noun_query& not_member_holonym_of(const noun& _noun); | ||
| 79 | |||
| 80 | noun_query& is_proper(bool _arg); | ||
| 81 | noun_query& is_not_proper(bool _arg); | ||
| 82 | |||
| 83 | noun_query& is_instance(bool _arg); | ||
| 84 | noun_query& instance_of(const noun& _noun); | ||
| 85 | noun_query& not_instance_of(const noun& _noun); | ||
| 86 | |||
| 87 | noun_query& is_class(bool _arg); | ||
| 88 | noun_query& class_of(const noun& _noun); | ||
| 89 | noun_query& not_class_of(const noun& _noun); | ||
| 90 | |||
| 91 | noun_query& has_synonyms(bool _arg); | ||
| 92 | noun_query& synonym_of(const noun& _noun); | ||
| 93 | noun_query& not_synonym_of(const noun& _noun); | ||
| 94 | |||
| 95 | noun_query& has_antonyms(bool _arg); | ||
| 96 | noun_query& antonym_of(const noun& _noun); | ||
| 97 | noun_query& not_antonym_of(const noun& _noun); | ||
| 98 | |||
| 99 | noun_query& has_pertainym(bool _arg); | ||
| 100 | noun_query& anti_pertainym_of(const adjective& _adj); | ||
| 101 | |||
| 102 | noun_query& is_attribute(bool _arg); | ||
| 103 | noun_query& attribute_of(const adjective& _adj); | ||
| 104 | |||
| 105 | noun_query& derived_from(const word& _w); | ||
| 106 | noun_query& not_derived_from(const word& _w); | ||
| 107 | |||
| 108 | std::list<noun> run() const; | ||
| 109 | |||
| 110 | const static int unlimited = -1; | ||
| 111 | |||
| 112 | private: | ||
| 113 | const data& _data; | ||
| 114 | int _limit = unlimited; | ||
| 115 | bool _random = false; | ||
| 116 | std::list<std::string> _rhymes; | ||
| 117 | std::list<noun> _except; | ||
| 118 | bool _has_prn = false; | ||
| 119 | |||
| 120 | bool _is_hypernym = false; | ||
| 121 | std::list<noun> _hypernym_of; | ||
| 122 | std::list<noun> _not_hypernym_of; | ||
| 123 | |||
| 124 | bool _is_hyponym = false; | ||
| 125 | std::list<noun> _hyponym_of; | ||
| 126 | std::list<noun> _not_hyponym_of; | ||
| 127 | |||
| 128 | bool _is_part_meronym = false; | ||
| 129 | std::list<noun> _part_meronym_of; | ||
| 130 | std::list<noun> _not_part_meronym_of; | ||
| 131 | |||
| 132 | bool _is_substance_meronym = false; | ||
| 133 | std::list<noun> _substance_meronym_of; | ||
| 134 | std::list<noun> _not_substance_meronym_of; | ||
| 135 | |||
| 136 | bool _is_member_meronym = false; | ||
| 137 | std::list<noun> _member_meronym_of; | ||
| 138 | std::list<noun> _not_member_meronym_of; | ||
| 139 | |||
| 140 | bool _is_part_holonym = false; | ||
| 141 | std::list<noun> _part_holonym_of; | ||
| 142 | std::list<noun> _not_part_holonym_of; | ||
| 143 | |||
| 144 | bool _is_substance_holonym = false; | ||
| 145 | std::list<noun> _substance_holonym_of; | ||
| 146 | std::list<noun> _not_substance_holonym_of; | ||
| 147 | |||
| 148 | bool _is_member_holonym = false; | ||
| 149 | std::list<noun> _member_holonym_of; | ||
| 150 | std::list<noun> _not_member_holonym_of; | ||
| 151 | |||
| 152 | bool _is_proper = false; | ||
| 153 | bool _is_not_proper = false; | ||
| 154 | |||
| 155 | bool _is_instance = false; | ||
| 156 | std::list<noun> _instance_of; | ||
| 157 | std::list<noun> _not_instance_of; | ||
| 158 | |||
| 159 | bool _is_class = false; | ||
| 160 | std::list<noun> _class_of; | ||
| 161 | std::list<noun> _not_class_of; | ||
| 162 | |||
| 163 | bool _has_synonyms = false; | ||
| 164 | std::list<noun> _synonym_of; | ||
| 165 | std::list<noun> _not_synonym_of; | ||
| 166 | |||
| 167 | bool _has_antonyms = false; | ||
| 168 | std::list<noun> _antonym_of; | ||
| 169 | std::list<noun> _not_antonym_of; | ||
| 170 | |||
| 171 | bool _has_pertainym = false; | ||
| 172 | std::list<adjective> _anti_pertainym_of; | ||
| 173 | |||
| 174 | bool _is_attribute = false; | ||
| 175 | std::list<adjective> _attribute_of; | ||
| 176 | 39 | ||
| 177 | std::list<adjective> _derived_from_adjective; | 40 | bool operator<(const noun& other) const; |
| 178 | std::list<adjective> _not_derived_from_adjective; | ||
| 179 | std::list<adverb> _derived_from_adverb; | ||
| 180 | std::list<adverb> _not_derived_from_adverb; | ||
| 181 | std::list<noun> _derived_from_noun; | ||
| 182 | std::list<noun> _not_derived_from_noun; | ||
| 183 | }; | 41 | }; |
| 184 | 42 | ||
| 185 | }; | 43 | }; |
| 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 @@ | |||
| 1 | #include "verbly.h" | ||
| 2 | |||
| 3 | namespace verbly { | ||
| 4 | |||
| 5 | noun_query::noun_query(const data& _data) : _data(_data) | ||
| 6 | { | ||
| 7 | |||
| 8 | } | ||
| 9 | |||
| 10 | noun_query& noun_query::limit(int _limit) | ||
| 11 | { | ||
| 12 | if ((_limit > 0) || (_limit == unlimited)) | ||
| 13 | { | ||
| 14 | this->_limit = _limit; | ||
| 15 | } | ||
| 16 | |||
| 17 | return *this; | ||
| 18 | } | ||
| 19 | |||
| 20 | noun_query& noun_query::random() | ||
| 21 | { | ||
| 22 | this->_random = true; | ||
| 23 | |||
| 24 | return *this; | ||
| 25 | } | ||
| 26 | |||
| 27 | noun_query& noun_query::except(const noun& _word) | ||
| 28 | { | ||
| 29 | _except.push_back(_word); | ||
| 30 | |||
| 31 | return *this; | ||
| 32 | } | ||
| 33 | |||
| 34 | noun_query& noun_query::rhymes_with(const word& _word) | ||
| 35 | { | ||
| 36 | for (auto rhyme : _word.rhyme_phonemes()) | ||
| 37 | { | ||
| 38 | _rhymes.push_back(rhyme); | ||
| 39 | } | ||
| 40 | |||
| 41 | if (dynamic_cast<const noun*>(&_word) != nullptr) | ||
| 42 | { | ||
| 43 | _except.push_back(dynamic_cast<const noun&>(_word)); | ||
| 44 | } | ||
| 45 | |||
| 46 | return *this; | ||
| 47 | } | ||
| 48 | |||
| 49 | noun_query& noun_query::has_pronunciation() | ||
| 50 | { | ||
| 51 | this->_has_prn = true; | ||
| 52 | |||
| 53 | return *this; | ||
| 54 | } | ||
| 55 | |||
| 56 | noun_query& noun_query::with_singular_form(std::string _arg) | ||
| 57 | { | ||
| 58 | _with_singular_form.push_back(_arg); | ||
| 59 | |||
| 60 | return *this; | ||
| 61 | } | ||
| 62 | |||
| 63 | noun_query& noun_query::is_hypernym() | ||
| 64 | { | ||
| 65 | _is_hypernym = true; | ||
| 66 | |||
| 67 | return *this; | ||
| 68 | } | ||
| 69 | |||
| 70 | noun_query& noun_query::hypernym_of(filter<noun> _f) | ||
| 71 | { | ||
| 72 | _f.clean(); | ||
| 73 | _hypernym_of = _f; | ||
| 74 | |||
| 75 | return *this; | ||
| 76 | } | ||
| 77 | |||
| 78 | noun_query& noun_query::full_hypernym_of(filter<noun> _f) | ||
| 79 | { | ||
| 80 | _f.clean(); | ||
| 81 | _full_hypernym_of = _f; | ||
| 82 | |||
| 83 | return *this; | ||
| 84 | } | ||
| 85 | |||
| 86 | noun_query& noun_query::is_hyponym() | ||
| 87 | { | ||
| 88 | _is_hyponym = true; | ||
| 89 | |||
| 90 | return *this; | ||
| 91 | } | ||
| 92 | |||
| 93 | noun_query& noun_query::hyponym_of(filter<noun> _f) | ||
| 94 | { | ||
| 95 | _f.clean(); | ||
| 96 | _hyponym_of = _f; | ||
| 97 | |||
| 98 | return *this; | ||
| 99 | } | ||
| 100 | |||
| 101 | noun_query& noun_query::full_hyponym_of(filter<noun> _f) | ||
| 102 | { | ||
| 103 | _f.clean(); | ||
| 104 | _full_hyponym_of = _f; | ||
| 105 | |||
| 106 | return *this; | ||
| 107 | } | ||
| 108 | |||
| 109 | noun_query& noun_query::is_part_meronym() | ||
| 110 | { | ||
| 111 | _is_part_meronym = true; | ||
| 112 | |||
| 113 | return *this; | ||
| 114 | } | ||
| 115 | |||
| 116 | noun_query& noun_query::part_meronym_of(filter<noun> _f) | ||
| 117 | { | ||
| 118 | _f.clean(); | ||
| 119 | _part_meronym_of = _f; | ||
| 120 | |||
| 121 | return *this; | ||
| 122 | } | ||
| 123 | |||
| 124 | noun_query& noun_query::is_part_holonym() | ||
| 125 | { | ||
| 126 | _is_part_holonym = true; | ||
| 127 | |||
| 128 | return *this; | ||
| 129 | } | ||
| 130 | |||
| 131 | noun_query& noun_query::part_holonym_of(filter<noun> _f) | ||
| 132 | { | ||
| 133 | _f.clean(); | ||
| 134 | _part_holonym_of = _f; | ||
| 135 | |||
| 136 | return *this; | ||
| 137 | } | ||
| 138 | |||
| 139 | noun_query& noun_query::is_substance_meronym() | ||
| 140 | { | ||
| 141 | _is_substance_meronym = true; | ||
| 142 | |||
| 143 | return *this; | ||
| 144 | } | ||
| 145 | |||
| 146 | noun_query& noun_query::substance_meronym_of(filter<noun> _f) | ||
| 147 | { | ||
| 148 | _f.clean(); | ||
| 149 | _substance_meronym_of = _f; | ||
| 150 | |||
| 151 | return *this; | ||
| 152 | } | ||
| 153 | |||
| 154 | noun_query& noun_query::is_substance_holonym() | ||
| 155 | { | ||
| 156 | _is_substance_holonym = true; | ||
| 157 | |||
| 158 | return *this; | ||
| 159 | } | ||
| 160 | |||
| 161 | noun_query& noun_query::substance_holonym_of(filter<noun> _f) | ||
| 162 | { | ||
| 163 | _f.clean(); | ||
| 164 | _substance_holonym_of = _f; | ||
| 165 | |||
| 166 | return *this; | ||
| 167 | } | ||
| 168 | |||
| 169 | noun_query& noun_query::is_member_meronym() | ||
| 170 | { | ||
| 171 | _is_member_meronym = true; | ||
| 172 | |||
| 173 | return *this; | ||
| 174 | } | ||
| 175 | |||
| 176 | noun_query& noun_query::member_meronym_of(filter<noun> _f) | ||
| 177 | { | ||
| 178 | _f.clean(); | ||
| 179 | _member_meronym_of = _f; | ||
| 180 | |||
| 181 | return *this; | ||
| 182 | } | ||
| 183 | |||
| 184 | noun_query& noun_query::is_member_holonym() | ||
| 185 | { | ||
| 186 | _is_member_holonym = true; | ||
| 187 | |||
| 188 | return *this; | ||
| 189 | } | ||
| 190 | |||
| 191 | noun_query& noun_query::member_holonym_of(filter<noun> _f) | ||
| 192 | { | ||
| 193 | _f.clean(); | ||
| 194 | _member_holonym_of = _f; | ||
| 195 | |||
| 196 | return *this; | ||
| 197 | } | ||
| 198 | |||
| 199 | noun_query& noun_query::is_proper() | ||
| 200 | { | ||
| 201 | _is_proper = true; | ||
| 202 | |||
| 203 | return *this; | ||
| 204 | } | ||
| 205 | |||
| 206 | noun_query& noun_query::is_not_proper() | ||
| 207 | { | ||
| 208 | _is_not_proper = true; | ||
| 209 | |||
| 210 | return *this; | ||
| 211 | } | ||
| 212 | |||
| 213 | noun_query& noun_query::is_instance() | ||
| 214 | { | ||
| 215 | _is_instance = true; | ||
| 216 | |||
| 217 | return *this; | ||
| 218 | } | ||
| 219 | |||
| 220 | noun_query& noun_query::instance_of(filter<noun> _f) | ||
| 221 | { | ||
| 222 | _f.clean(); | ||
| 223 | _instance_of = _f; | ||
| 224 | |||
| 225 | return *this; | ||
| 226 | } | ||
| 227 | |||
| 228 | noun_query& noun_query::is_class() | ||
| 229 | { | ||
| 230 | _is_class = true; | ||
| 231 | |||
| 232 | return *this; | ||
| 233 | } | ||
| 234 | |||
| 235 | noun_query& noun_query::class_of(filter<noun> _f) | ||
| 236 | { | ||
| 237 | _f.clean(); | ||
| 238 | _class_of = _f; | ||
| 239 | |||
| 240 | return *this; | ||
| 241 | } | ||
| 242 | |||
| 243 | noun_query& noun_query::has_synonyms() | ||
| 244 | { | ||
| 245 | _has_synonyms = true; | ||
| 246 | |||
| 247 | return *this; | ||
| 248 | } | ||
| 249 | |||
| 250 | noun_query& noun_query::synonym_of(filter<noun> _f) | ||
| 251 | { | ||
| 252 | _f.clean(); | ||
| 253 | _synonym_of = _f; | ||
| 254 | |||
| 255 | return *this; | ||
| 256 | } | ||
| 257 | |||
| 258 | noun_query& noun_query::has_antonyms() | ||
| 259 | { | ||
| 260 | _has_antonyms = true; | ||
| 261 | |||
| 262 | return *this; | ||
| 263 | } | ||
| 264 | |||
| 265 | noun_query& noun_query::antonym_of(filter<noun> _f) | ||
| 266 | { | ||
| 267 | _f.clean(); | ||
| 268 | _antonym_of = _f; | ||
| 269 | |||
| 270 | return *this; | ||
| 271 | } | ||
| 272 | |||
| 273 | noun_query& noun_query::has_pertainym() | ||
| 274 | { | ||
| 275 | _has_pertainym = true; | ||
| 276 | |||
| 277 | return *this; | ||
| 278 | } | ||
| 279 | |||
| 280 | noun_query& noun_query::anti_pertainym_of(filter<adjective> _f) | ||
| 281 | { | ||
| 282 | _f.clean(); | ||
| 283 | _anti_pertainym_of = _f; | ||
| 284 | |||
| 285 | return *this; | ||
| 286 | } | ||
| 287 | |||
| 288 | noun_query& noun_query::is_attribute() | ||
| 289 | { | ||
| 290 | _is_attribute = true; | ||
| 291 | |||
| 292 | return *this; | ||
| 293 | } | ||
| 294 | |||
| 295 | noun_query& noun_query::attribute_of(filter<adjective> _f) | ||
| 296 | { | ||
| 297 | _f.clean(); | ||
| 298 | _attribute_of = _f; | ||
| 299 | |||
| 300 | return *this; | ||
| 301 | } | ||
| 302 | /* | ||
| 303 | noun_query& noun_query::derived_from(const word& _w) | ||
| 304 | { | ||
| 305 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
| 306 | { | ||
| 307 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 308 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 309 | { | ||
| 310 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 311 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 312 | { | ||
| 313 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 314 | } | ||
| 315 | |||
| 316 | return *this; | ||
| 317 | } | ||
| 318 | |||
| 319 | noun_query& noun_query::not_derived_from(const word& _w) | ||
| 320 | { | ||
| 321 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
| 322 | { | ||
| 323 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
| 324 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
| 325 | { | ||
| 326 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
| 327 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
| 328 | { | ||
| 329 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
| 330 | } | ||
| 331 | |||
| 332 | return *this; | ||
| 333 | }*/ | ||
| 334 | |||
| 335 | std::list<noun> noun_query::run() const | ||
| 336 | { | ||
| 337 | std::stringstream construct; | ||
| 338 | |||
| 339 | if (!_full_hypernym_of.empty() || !_full_hyponym_of.empty()) | ||
| 340 | { | ||
| 341 | construct << "WITH RECURSIVE "; | ||
| 342 | |||
| 343 | std::list<std::string> ctes; | ||
| 344 | |||
| 345 | for (auto hyponym : _full_hypernym_of.uniq_flatten()) | ||
| 346 | { | ||
| 347 | 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)"); | ||
| 348 | } | ||
| 349 | |||
| 350 | for (auto hypernym : _full_hyponym_of.uniq_flatten()) | ||
| 351 | { | ||
| 352 | 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)"); | ||
| 353 | } | ||
| 354 | |||
| 355 | construct << verbly::implode(std::begin(ctes), std::end(ctes), ", "); | ||
| 356 | construct << " "; | ||
| 357 | } | ||
| 358 | |||
| 359 | construct << "SELECT noun_id, singular, plural FROM nouns"; | ||
| 360 | std::list<std::string> conditions; | ||
| 361 | |||
| 362 | if (_has_prn) | ||
| 363 | { | ||
| 364 | conditions.push_back("noun_id IN (SELECT noun_id FROM noun_pronunciations)"); | ||
| 365 | } | ||
| 366 | |||
| 367 | if (!_rhymes.empty()) | ||
| 368 | { | ||
| 369 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
| 370 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 371 | conditions.push_back(cond); | ||
| 372 | } | ||
| 373 | |||
| 374 | for (auto except : _except) | ||
| 375 | { | ||
| 376 | conditions.push_back("noun_id != @EXCID"); | ||
| 377 | } | ||
| 378 | |||
| 379 | if (!_with_singular_form.empty()) | ||
| 380 | { | ||
| 381 | std::list<std::string> clauses(_with_singular_form.size(), "singular = @SFORM"); | ||
| 382 | std::string cond = "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 383 | conditions.push_back(cond); | ||
| 384 | } | ||
| 385 | |||
| 386 | if (_is_hypernym) | ||
| 387 | { | ||
| 388 | conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)"); | ||
| 389 | } | ||
| 390 | |||
| 391 | if (!_hypernym_of.empty()) | ||
| 392 | { | ||
| 393 | std::stringstream cond; | ||
| 394 | if (_hypernym_of.get_notlogic()) | ||
| 395 | { | ||
| 396 | cond << "noun_id NOT IN"; | ||
| 397 | } else { | ||
| 398 | cond << "noun_id IN"; | ||
| 399 | } | ||
| 400 | |||
| 401 | cond << "(SELECT hypernym_id FROM hypernymy WHERE "; | ||
| 402 | |||
| 403 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 404 | switch (f.get_type()) | ||
| 405 | { | ||
| 406 | case filter<noun>::type::singleton: | ||
| 407 | { | ||
| 408 | if (notlogic == f.get_notlogic()) | ||
| 409 | { | ||
| 410 | return "hyponym_id = @HYPO"; | ||
| 411 | } else { | ||
| 412 | return "hyponym_id != @HYPO"; | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | case filter<noun>::type::group: | ||
| 417 | { | ||
| 418 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 419 | |||
| 420 | std::list<std::string> clauses; | ||
| 421 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 422 | return recur(f2, truelogic); | ||
| 423 | }); | ||
| 424 | |||
| 425 | if (truelogic == f.get_orlogic()) | ||
| 426 | { | ||
| 427 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 428 | } else { | ||
| 429 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | } | ||
| 433 | }; | ||
| 434 | |||
| 435 | cond << recur(_hypernym_of, _hypernym_of.get_notlogic()); | ||
| 436 | cond << ")"; | ||
| 437 | conditions.push_back(cond.str()); | ||
| 438 | } | ||
| 439 | |||
| 440 | if (!_full_hypernym_of.empty()) | ||
| 441 | { | ||
| 442 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 443 | switch (f.get_type()) | ||
| 444 | { | ||
| 445 | case filter<noun>::type::singleton: | ||
| 446 | { | ||
| 447 | if (notlogic == f.get_notlogic()) | ||
| 448 | { | ||
| 449 | return "noun_id IN (SELECT hypernym_id FROM hypernym_tree_" + std::to_string(f.get_elem()._id) + ")"; | ||
| 450 | } else { | ||
| 451 | return "noun_id NOT IN (SELECT hypernym_id FROM hypernym_tree_" + std::to_string(f.get_elem()._id) + ")"; | ||
| 452 | } | ||
| 453 | } | ||
| 454 | |||
| 455 | case filter<noun>::type::group: | ||
| 456 | { | ||
| 457 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 458 | |||
| 459 | std::list<std::string> clauses; | ||
| 460 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 461 | return recur(f2, truelogic); | ||
| 462 | }); | ||
| 463 | |||
| 464 | if (truelogic == f.get_orlogic()) | ||
| 465 | { | ||
| 466 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 467 | } else { | ||
| 468 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | } | ||
| 472 | }; | ||
| 473 | |||
| 474 | conditions.push_back(recur(_full_hypernym_of, false)); | ||
| 475 | } | ||
| 476 | |||
| 477 | if (!_full_hyponym_of.empty()) | ||
| 478 | { | ||
| 479 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 480 | switch (f.get_type()) | ||
| 481 | { | ||
| 482 | case filter<noun>::type::singleton: | ||
| 483 | { | ||
| 484 | if (notlogic == f.get_notlogic()) | ||
| 485 | { | ||
| 486 | return "noun_id IN (SELECT hyponym_id FROM hyponym_tree_" + std::to_string(f.get_elem()._id) + ")"; | ||
| 487 | } else { | ||
| 488 | return "noun_id NOT IN (SELECT hyponym_id FROM hyponym_tree_" + std::to_string(f.get_elem()._id) + ")"; | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 492 | case filter<noun>::type::group: | ||
| 493 | { | ||
| 494 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 495 | |||
| 496 | std::list<std::string> clauses; | ||
| 497 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 498 | return recur(f2, truelogic); | ||
| 499 | }); | ||
| 500 | |||
| 501 | if (truelogic == f.get_orlogic()) | ||
| 502 | { | ||
| 503 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 504 | } else { | ||
| 505 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 506 | } | ||
| 507 | } | ||
| 508 | } | ||
| 509 | }; | ||
| 510 | |||
| 511 | conditions.push_back(recur(_full_hyponym_of, false)); | ||
| 512 | } | ||
| 513 | |||
| 514 | if (_is_hyponym) | ||
| 515 | { | ||
| 516 | conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)"); | ||
| 517 | } | ||
| 518 | |||
| 519 | if (!_hyponym_of.empty()) | ||
| 520 | { | ||
| 521 | std::stringstream cond; | ||
| 522 | if (_hyponym_of.get_notlogic()) | ||
| 523 | { | ||
| 524 | cond << "noun_id NOT IN"; | ||
| 525 | } else { | ||
| 526 | cond << "noun_id IN"; | ||
| 527 | } | ||
| 528 | |||
| 529 | cond << "(SELECT hyponym_id FROM hypernymy WHERE "; | ||
| 530 | |||
| 531 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 532 | switch (f.get_type()) | ||
| 533 | { | ||
| 534 | case filter<noun>::type::singleton: | ||
| 535 | { | ||
| 536 | if (notlogic == f.get_notlogic()) | ||
| 537 | { | ||
| 538 | return "hypernym_id = @HYPER"; | ||
| 539 | } else { | ||
| 540 | return "hypernym_id != @HYPER"; | ||
| 541 | } | ||
| 542 | } | ||
| 543 | |||
| 544 | case filter<noun>::type::group: | ||
| 545 | { | ||
| 546 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 547 | |||
| 548 | std::list<std::string> clauses; | ||
| 549 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 550 | return recur(f2, truelogic); | ||
| 551 | }); | ||
| 552 | |||
| 553 | if (truelogic == f.get_orlogic()) | ||
| 554 | { | ||
| 555 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 556 | } else { | ||
| 557 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 558 | } | ||
| 559 | } | ||
| 560 | } | ||
| 561 | }; | ||
| 562 | |||
| 563 | cond << recur(_hyponym_of, _hyponym_of.get_notlogic()); | ||
| 564 | cond << ")"; | ||
| 565 | conditions.push_back(cond.str()); | ||
| 566 | } | ||
| 567 | |||
| 568 | if (_is_part_meronym) | ||
| 569 | { | ||
| 570 | conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)"); | ||
| 571 | } | ||
| 572 | |||
| 573 | if (!_part_meronym_of.empty()) | ||
| 574 | { | ||
| 575 | std::stringstream cond; | ||
| 576 | if (_part_meronym_of.get_notlogic()) | ||
| 577 | { | ||
| 578 | cond << "noun_id NOT IN"; | ||
| 579 | } else { | ||
| 580 | cond << "noun_id IN"; | ||
| 581 | } | ||
| 582 | |||
| 583 | cond << "(SELECT meronym_id FROM part_meronymy WHERE "; | ||
| 584 | |||
| 585 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 586 | switch (f.get_type()) | ||
| 587 | { | ||
| 588 | case filter<noun>::type::singleton: | ||
| 589 | { | ||
| 590 | if (notlogic == f.get_notlogic()) | ||
| 591 | { | ||
| 592 | return "holonym_id = @PHOLO"; | ||
| 593 | } else { | ||
| 594 | return "holonym_id != @PHOLO"; | ||
| 595 | } | ||
| 596 | } | ||
| 597 | |||
| 598 | case filter<noun>::type::group: | ||
| 599 | { | ||
| 600 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 601 | |||
| 602 | std::list<std::string> clauses; | ||
| 603 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 604 | return recur(f2, truelogic); | ||
| 605 | }); | ||
| 606 | |||
| 607 | if (truelogic == f.get_orlogic()) | ||
| 608 | { | ||
| 609 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 610 | } else { | ||
| 611 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 612 | } | ||
| 613 | } | ||
| 614 | } | ||
| 615 | }; | ||
| 616 | |||
| 617 | cond << recur(_part_meronym_of, _part_meronym_of.get_notlogic()); | ||
| 618 | cond << ")"; | ||
| 619 | conditions.push_back(cond.str()); | ||
| 620 | } | ||
| 621 | |||
| 622 | if (_is_part_holonym) | ||
| 623 | { | ||
| 624 | conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)"); | ||
| 625 | } | ||
| 626 | |||
| 627 | if (!_part_holonym_of.empty()) | ||
| 628 | { | ||
| 629 | std::stringstream cond; | ||
| 630 | if (_part_holonym_of.get_notlogic()) | ||
| 631 | { | ||
| 632 | cond << "noun_id NOT IN"; | ||
| 633 | } else { | ||
| 634 | cond << "noun_id IN"; | ||
| 635 | } | ||
| 636 | |||
| 637 | cond << "(SELECT holonym_id FROM part_meronymy WHERE "; | ||
| 638 | |||
| 639 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 640 | switch (f.get_type()) | ||
| 641 | { | ||
| 642 | case filter<noun>::type::singleton: | ||
| 643 | { | ||
| 644 | if (notlogic == f.get_notlogic()) | ||
| 645 | { | ||
| 646 | return "meronym_id = @PMERO"; | ||
| 647 | } else { | ||
| 648 | return "meronym_id != @PMERO"; | ||
| 649 | } | ||
| 650 | } | ||
| 651 | |||
| 652 | case filter<noun>::type::group: | ||
| 653 | { | ||
| 654 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 655 | |||
| 656 | std::list<std::string> clauses; | ||
| 657 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 658 | return recur(f2, truelogic); | ||
| 659 | }); | ||
| 660 | |||
| 661 | if (truelogic == f.get_orlogic()) | ||
| 662 | { | ||
| 663 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 664 | } else { | ||
| 665 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 666 | } | ||
| 667 | } | ||
| 668 | } | ||
| 669 | }; | ||
| 670 | |||
| 671 | cond << recur(_part_holonym_of, _part_holonym_of.get_notlogic()); | ||
| 672 | cond << ")"; | ||
| 673 | conditions.push_back(cond.str()); | ||
| 674 | } | ||
| 675 | |||
| 676 | if (_is_substance_meronym) | ||
| 677 | { | ||
| 678 | conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)"); | ||
| 679 | } | ||
| 680 | |||
| 681 | if (!_substance_meronym_of.empty()) | ||
| 682 | { | ||
| 683 | std::stringstream cond; | ||
| 684 | if (_substance_meronym_of.get_notlogic()) | ||
| 685 | { | ||
| 686 | cond << "noun_id NOT IN"; | ||
| 687 | } else { | ||
| 688 | cond << "noun_id IN"; | ||
| 689 | } | ||
| 690 | |||
| 691 | cond << "(SELECT meronym_id FROM substance_meronymy WHERE "; | ||
| 692 | |||
| 693 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 694 | switch (f.get_type()) | ||
| 695 | { | ||
| 696 | case filter<noun>::type::singleton: | ||
| 697 | { | ||
| 698 | if (notlogic == f.get_notlogic()) | ||
| 699 | { | ||
| 700 | return "holonym_id = @SHOLO"; | ||
| 701 | } else { | ||
| 702 | return "holonym_id != @SHOLO"; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | case filter<noun>::type::group: | ||
| 707 | { | ||
| 708 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 709 | |||
| 710 | std::list<std::string> clauses; | ||
| 711 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 712 | return recur(f2, truelogic); | ||
| 713 | }); | ||
| 714 | |||
| 715 | if (truelogic == f.get_orlogic()) | ||
| 716 | { | ||
| 717 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 718 | } else { | ||
| 719 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 720 | } | ||
| 721 | } | ||
| 722 | } | ||
| 723 | }; | ||
| 724 | |||
| 725 | cond << recur(_substance_meronym_of, _substance_meronym_of.get_notlogic()); | ||
| 726 | cond << ")"; | ||
| 727 | conditions.push_back(cond.str()); | ||
| 728 | } | ||
| 729 | |||
| 730 | if (_is_substance_holonym) | ||
| 731 | { | ||
| 732 | conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)"); | ||
| 733 | } | ||
| 734 | |||
| 735 | if (!_substance_holonym_of.empty()) | ||
| 736 | { | ||
| 737 | std::stringstream cond; | ||
| 738 | if (_substance_holonym_of.get_notlogic()) | ||
| 739 | { | ||
| 740 | cond << "noun_id NOT IN"; | ||
| 741 | } else { | ||
| 742 | cond << "noun_id IN"; | ||
| 743 | } | ||
| 744 | |||
| 745 | cond << "(SELECT holonym_id FROM substance_meronymy WHERE "; | ||
| 746 | |||
| 747 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 748 | switch (f.get_type()) | ||
| 749 | { | ||
| 750 | case filter<noun>::type::singleton: | ||
| 751 | { | ||
| 752 | if (notlogic == f.get_notlogic()) | ||
| 753 | { | ||
| 754 | return "meronym_id = @SMERO"; | ||
| 755 | } else { | ||
| 756 | return "meronym_id != @SMERO"; | ||
| 757 | } | ||
| 758 | } | ||
| 759 | |||
| 760 | case filter<noun>::type::group: | ||
| 761 | { | ||
| 762 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 763 | |||
| 764 | std::list<std::string> clauses; | ||
| 765 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 766 | return recur(f2, truelogic); | ||
| 767 | }); | ||
| 768 | |||
| 769 | if (truelogic == f.get_orlogic()) | ||
| 770 | { | ||
| 771 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 772 | } else { | ||
| 773 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 774 | } | ||
| 775 | } | ||
| 776 | } | ||
| 777 | }; | ||
| 778 | |||
| 779 | cond << recur(_substance_holonym_of, _substance_holonym_of.get_notlogic()); | ||
| 780 | cond << ")"; | ||
| 781 | conditions.push_back(cond.str()); | ||
| 782 | } | ||
| 783 | |||
| 784 | if (_is_member_meronym) | ||
| 785 | { | ||
| 786 | conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)"); | ||
| 787 | } | ||
| 788 | |||
| 789 | if (!_member_meronym_of.empty()) | ||
| 790 | { | ||
| 791 | std::stringstream cond; | ||
| 792 | if (_member_meronym_of.get_notlogic()) | ||
| 793 | { | ||
| 794 | cond << "noun_id NOT IN"; | ||
| 795 | } else { | ||
| 796 | cond << "noun_id IN"; | ||
| 797 | } | ||
| 798 | |||
| 799 | cond << "(SELECT meronym_id FROM member_meronymy WHERE "; | ||
| 800 | |||
| 801 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 802 | switch (f.get_type()) | ||
| 803 | { | ||
| 804 | case filter<noun>::type::singleton: | ||
| 805 | { | ||
| 806 | if (notlogic == f.get_notlogic()) | ||
| 807 | { | ||
| 808 | return "holonym_id = @MHOLO"; | ||
| 809 | } else { | ||
| 810 | return "holonym_id != @MHOLO"; | ||
| 811 | } | ||
| 812 | } | ||
| 813 | |||
| 814 | case filter<noun>::type::group: | ||
| 815 | { | ||
| 816 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 817 | |||
| 818 | std::list<std::string> clauses; | ||
| 819 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 820 | return recur(f2, truelogic); | ||
| 821 | }); | ||
| 822 | |||
| 823 | if (truelogic == f.get_orlogic()) | ||
| 824 | { | ||
| 825 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 826 | } else { | ||
| 827 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 828 | } | ||
| 829 | } | ||
| 830 | } | ||
| 831 | }; | ||
| 832 | |||
| 833 | cond << recur(_member_meronym_of, _member_meronym_of.get_notlogic()); | ||
| 834 | cond << ")"; | ||
| 835 | conditions.push_back(cond.str()); | ||
| 836 | } | ||
| 837 | |||
| 838 | if (_is_member_holonym) | ||
| 839 | { | ||
| 840 | conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)"); | ||
| 841 | } | ||
| 842 | |||
| 843 | if (!_member_holonym_of.empty()) | ||
| 844 | { | ||
| 845 | std::stringstream cond; | ||
| 846 | if (_member_holonym_of.get_notlogic()) | ||
| 847 | { | ||
| 848 | cond << "noun_id NOT IN"; | ||
| 849 | } else { | ||
| 850 | cond << "noun_id IN"; | ||
| 851 | } | ||
| 852 | |||
| 853 | cond << "(SELECT holonym_id FROM member_meronymy WHERE "; | ||
| 854 | |||
| 855 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 856 | switch (f.get_type()) | ||
| 857 | { | ||
| 858 | case filter<noun>::type::singleton: | ||
| 859 | { | ||
| 860 | if (notlogic == f.get_notlogic()) | ||
| 861 | { | ||
| 862 | return "meronym_id = @MMERO"; | ||
| 863 | } else { | ||
| 864 | return "meronym_id != @MMERO"; | ||
| 865 | } | ||
| 866 | } | ||
| 867 | |||
| 868 | case filter<noun>::type::group: | ||
| 869 | { | ||
| 870 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 871 | |||
| 872 | std::list<std::string> clauses; | ||
| 873 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 874 | return recur(f2, truelogic); | ||
| 875 | }); | ||
| 876 | |||
| 877 | if (truelogic == f.get_orlogic()) | ||
| 878 | { | ||
| 879 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 880 | } else { | ||
| 881 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 882 | } | ||
| 883 | } | ||
| 884 | } | ||
| 885 | }; | ||
| 886 | |||
| 887 | cond << recur(_member_holonym_of, _member_holonym_of.get_notlogic()); | ||
| 888 | cond << ")"; | ||
| 889 | conditions.push_back(cond.str()); | ||
| 890 | } | ||
| 891 | |||
| 892 | if (_is_proper) | ||
| 893 | { | ||
| 894 | conditions.push_back("proper = 1"); | ||
| 895 | } | ||
| 896 | |||
| 897 | if (_is_not_proper) | ||
| 898 | { | ||
| 899 | conditions.push_back("proper = 0"); | ||
| 900 | } | ||
| 901 | |||
| 902 | if (_is_instance) | ||
| 903 | { | ||
| 904 | conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)"); | ||
| 905 | } | ||
| 906 | |||
| 907 | if (!_instance_of.empty()) | ||
| 908 | { | ||
| 909 | std::stringstream cond; | ||
| 910 | if (_instance_of.get_notlogic()) | ||
| 911 | { | ||
| 912 | cond << "noun_id NOT IN"; | ||
| 913 | } else { | ||
| 914 | cond << "noun_id IN"; | ||
| 915 | } | ||
| 916 | |||
| 917 | cond << "(SELECT instance_id FROM instantiation WHERE "; | ||
| 918 | |||
| 919 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 920 | switch (f.get_type()) | ||
| 921 | { | ||
| 922 | case filter<noun>::type::singleton: | ||
| 923 | { | ||
| 924 | if (notlogic == f.get_notlogic()) | ||
| 925 | { | ||
| 926 | return "class_id = @CLSID"; | ||
| 927 | } else { | ||
| 928 | return "class_id != @CLSID"; | ||
| 929 | } | ||
| 930 | } | ||
| 931 | |||
| 932 | case filter<noun>::type::group: | ||
| 933 | { | ||
| 934 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 935 | |||
| 936 | std::list<std::string> clauses; | ||
| 937 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 938 | return recur(f2, truelogic); | ||
| 939 | }); | ||
| 940 | |||
| 941 | if (truelogic == f.get_orlogic()) | ||
| 942 | { | ||
| 943 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 944 | } else { | ||
| 945 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 946 | } | ||
| 947 | } | ||
| 948 | } | ||
| 949 | }; | ||
| 950 | |||
| 951 | cond << recur(_instance_of, _instance_of.get_notlogic()); | ||
| 952 | cond << ")"; | ||
| 953 | conditions.push_back(cond.str()); | ||
| 954 | } | ||
| 955 | |||
| 956 | if (_is_class) | ||
| 957 | { | ||
| 958 | conditions.push_back("noun_id IN (SELECT class_id FROM instantiation)"); | ||
| 959 | } | ||
| 960 | |||
| 961 | if (!_class_of.empty()) | ||
| 962 | { | ||
| 963 | std::stringstream cond; | ||
| 964 | if (_class_of.get_notlogic()) | ||
| 965 | { | ||
| 966 | cond << "noun_id NOT IN"; | ||
| 967 | } else { | ||
| 968 | cond << "noun_id IN"; | ||
| 969 | } | ||
| 970 | |||
| 971 | cond << "(SELECT class_id FROM instantiation WHERE "; | ||
| 972 | |||
| 973 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 974 | switch (f.get_type()) | ||
| 975 | { | ||
| 976 | case filter<noun>::type::singleton: | ||
| 977 | { | ||
| 978 | if (notlogic == f.get_notlogic()) | ||
| 979 | { | ||
| 980 | return "instance_id = @INSID"; | ||
| 981 | } else { | ||
| 982 | return "instance_id != @INSID"; | ||
| 983 | } | ||
| 984 | } | ||
| 985 | |||
| 986 | case filter<noun>::type::group: | ||
| 987 | { | ||
| 988 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 989 | |||
| 990 | std::list<std::string> clauses; | ||
| 991 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 992 | return recur(f2, truelogic); | ||
| 993 | }); | ||
| 994 | |||
| 995 | if (truelogic == f.get_orlogic()) | ||
| 996 | { | ||
| 997 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 998 | } else { | ||
| 999 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1000 | } | ||
| 1001 | } | ||
| 1002 | } | ||
| 1003 | }; | ||
| 1004 | |||
| 1005 | cond << recur(_class_of, _class_of.get_notlogic()); | ||
| 1006 | cond << ")"; | ||
| 1007 | conditions.push_back(cond.str()); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | if (_has_synonyms) | ||
| 1011 | { | ||
| 1012 | conditions.push_back("noun_id IN (SELECT noun_2_id FROM noun_synonymy)"); | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | if (!_synonym_of.empty()) | ||
| 1016 | { | ||
| 1017 | std::stringstream cond; | ||
| 1018 | if (_synonym_of.get_notlogic()) | ||
| 1019 | { | ||
| 1020 | cond << "noun_id NOT IN"; | ||
| 1021 | } else { | ||
| 1022 | cond << "noun_id IN"; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | cond << "(SELECT noun_2_id FROM noun_synonymy WHERE "; | ||
| 1026 | |||
| 1027 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 1028 | switch (f.get_type()) | ||
| 1029 | { | ||
| 1030 | case filter<noun>::type::singleton: | ||
| 1031 | { | ||
| 1032 | if (notlogic == f.get_notlogic()) | ||
| 1033 | { | ||
| 1034 | return "noun_1_id = @SYNID"; | ||
| 1035 | } else { | ||
| 1036 | return "noun_1_id != @SYNID"; | ||
| 1037 | } | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | case filter<noun>::type::group: | ||
| 1041 | { | ||
| 1042 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 1043 | |||
| 1044 | std::list<std::string> clauses; | ||
| 1045 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 1046 | return recur(f2, truelogic); | ||
| 1047 | }); | ||
| 1048 | |||
| 1049 | if (truelogic == f.get_orlogic()) | ||
| 1050 | { | ||
| 1051 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 1052 | } else { | ||
| 1053 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1054 | } | ||
| 1055 | } | ||
| 1056 | } | ||
| 1057 | }; | ||
| 1058 | |||
| 1059 | cond << recur(_synonym_of, _synonym_of.get_notlogic()); | ||
| 1060 | cond << ")"; | ||
| 1061 | conditions.push_back(cond.str()); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | if (_has_antonyms) | ||
| 1065 | { | ||
| 1066 | conditions.push_back("noun_id IN (SELECT noun_2_id FROM noun_antonymy)"); | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | if (!_antonym_of.empty()) | ||
| 1070 | { | ||
| 1071 | std::stringstream cond; | ||
| 1072 | if (_antonym_of.get_notlogic()) | ||
| 1073 | { | ||
| 1074 | cond << "noun_id NOT IN"; | ||
| 1075 | } else { | ||
| 1076 | cond << "noun_id IN"; | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | cond << "(SELECT noun_2_id FROM noun_antonymy WHERE "; | ||
| 1080 | |||
| 1081 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
| 1082 | switch (f.get_type()) | ||
| 1083 | { | ||
| 1084 | case filter<noun>::type::singleton: | ||
| 1085 | { | ||
| 1086 | if (notlogic == f.get_notlogic()) | ||
| 1087 | { | ||
| 1088 | return "noun_1_id = @ANTID"; | ||
| 1089 | } else { | ||
| 1090 | return "noun_1_id != @ANTID"; | ||
| 1091 | } | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | case filter<noun>::type::group: | ||
| 1095 | { | ||
| 1096 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 1097 | |||
| 1098 | std::list<std::string> clauses; | ||
| 1099 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
| 1100 | return recur(f2, truelogic); | ||
| 1101 | }); | ||
| 1102 | |||
| 1103 | if (truelogic == f.get_orlogic()) | ||
| 1104 | { | ||
| 1105 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 1106 | } else { | ||
| 1107 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1108 | } | ||
| 1109 | } | ||
| 1110 | } | ||
| 1111 | }; | ||
| 1112 | |||
| 1113 | cond << recur(_antonym_of, _antonym_of.get_notlogic()); | ||
| 1114 | cond << ")"; | ||
| 1115 | conditions.push_back(cond.str()); | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | if (_has_pertainym) | ||
| 1119 | { | ||
| 1120 | conditions.push_back("noun_id IN (SELECT noun_id FROM pertainymy)"); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | if (!_anti_pertainym_of.empty()) | ||
| 1124 | { | ||
| 1125 | std::stringstream cond; | ||
| 1126 | if (_anti_pertainym_of.get_notlogic()) | ||
| 1127 | { | ||
| 1128 | cond << "noun_id NOT IN"; | ||
| 1129 | } else { | ||
| 1130 | cond << "noun_id IN"; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | cond << "(SELECT noun_id FROM pertainymy WHERE "; | ||
| 1134 | |||
| 1135 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
| 1136 | switch (f.get_type()) | ||
| 1137 | { | ||
| 1138 | case filter<adjective>::type::singleton: | ||
| 1139 | { | ||
| 1140 | if (notlogic == f.get_notlogic()) | ||
| 1141 | { | ||
| 1142 | return "pertainym_id = @PERID"; | ||
| 1143 | } else { | ||
| 1144 | return "pertainym_id != @PERID"; | ||
| 1145 | } | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | case filter<adjective>::type::group: | ||
| 1149 | { | ||
| 1150 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 1151 | |||
| 1152 | std::list<std::string> clauses; | ||
| 1153 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
| 1154 | return recur(f2, truelogic); | ||
| 1155 | }); | ||
| 1156 | |||
| 1157 | if (truelogic == f.get_orlogic()) | ||
| 1158 | { | ||
| 1159 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 1160 | } else { | ||
| 1161 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1162 | } | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | }; | ||
| 1166 | |||
| 1167 | cond << recur(_anti_pertainym_of, _anti_pertainym_of.get_notlogic()); | ||
| 1168 | cond << ")"; | ||
| 1169 | conditions.push_back(cond.str()); | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | if (_is_attribute) | ||
| 1173 | { | ||
| 1174 | conditions.push_back("noun_id IN (SELECT noun_id FROM variation)"); | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | if (!_attribute_of.empty()) | ||
| 1178 | { | ||
| 1179 | std::stringstream cond; | ||
| 1180 | if (_attribute_of.get_notlogic()) | ||
| 1181 | { | ||
| 1182 | cond << "noun_id NOT IN"; | ||
| 1183 | } else { | ||
| 1184 | cond << "noun_id IN"; | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | cond << "(SELECT noun_id FROM variation WHERE "; | ||
| 1188 | |||
| 1189 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
| 1190 | switch (f.get_type()) | ||
| 1191 | { | ||
| 1192 | case filter<adjective>::type::singleton: | ||
| 1193 | { | ||
| 1194 | if (notlogic == f.get_notlogic()) | ||
| 1195 | { | ||
| 1196 | return "adjective_id = @VALID"; | ||
| 1197 | } else { | ||
| 1198 | return "adjective_id != @VALID"; | ||
| 1199 | } | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | case filter<adjective>::type::group: | ||
| 1203 | { | ||
| 1204 | bool truelogic = notlogic != f.get_notlogic(); | ||
| 1205 | |||
| 1206 | std::list<std::string> clauses; | ||
| 1207 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
| 1208 | return recur(f2, truelogic); | ||
| 1209 | }); | ||
| 1210 | |||
| 1211 | if (truelogic == f.get_orlogic()) | ||
| 1212 | { | ||
| 1213 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
| 1214 | } else { | ||
| 1215 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1216 | } | ||
| 1217 | } | ||
| 1218 | } | ||
| 1219 | }; | ||
| 1220 | |||
| 1221 | cond << recur(_attribute_of, _attribute_of.get_notlogic()); | ||
| 1222 | cond << ")"; | ||
| 1223 | conditions.push_back(cond.str()); | ||
| 1224 | } | ||
| 1225 | /* | ||
| 1226 | if (!_derived_from_adjective.empty()) | ||
| 1227 | { | ||
| 1228 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); | ||
| 1229 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1230 | conditions.push_back(cond); | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | if (!_not_derived_from_adjective.empty()) | ||
| 1234 | { | ||
| 1235 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); | ||
| 1236 | std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1237 | conditions.push_back(cond); | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | if (!_derived_from_adverb.empty()) | ||
| 1241 | { | ||
| 1242 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); | ||
| 1243 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1244 | conditions.push_back(cond); | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | if (!_not_derived_from_adverb.empty()) | ||
| 1248 | { | ||
| 1249 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); | ||
| 1250 | std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1251 | conditions.push_back(cond); | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | if (!_derived_from_noun.empty()) | ||
| 1255 | { | ||
| 1256 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_2_id = @DERN"); | ||
| 1257 | std::string cond = "noun_id IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 1258 | conditions.push_back(cond); | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | if (!_not_derived_from_noun.empty()) | ||
| 1262 | { | ||
| 1263 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_2_id = @NDERN"); | ||
| 1264 | 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 ") + ")"; | ||
| 1265 | conditions.push_back(cond); | ||
| 1266 | } | ||
| 1267 | */ | ||
| 1268 | if (!conditions.empty()) | ||
| 1269 | { | ||
| 1270 | construct << " WHERE "; | ||
| 1271 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | if (_random) | ||
| 1275 | { | ||
| 1276 | construct << " ORDER BY RANDOM()"; | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | if (_limit != unlimited) | ||
| 1280 | { | ||
| 1281 | construct << " LIMIT " << _limit; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | sqlite3_stmt* ppstmt; | ||
| 1285 | std::string query = construct.str(); | ||
| 1286 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 1287 | { | ||
| 1288 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | if (!_rhymes.empty()) | ||
| 1292 | { | ||
| 1293 | int i = 0; | ||
| 1294 | for (auto rhyme : _rhymes) | ||
| 1295 | { | ||
| 1296 | std::string rhymer = "%" + rhyme; | ||
| 1297 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
| 1298 | |||
| 1299 | i++; | ||
| 1300 | } | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | for (auto except : _except) | ||
| 1304 | { | ||
| 1305 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | for (auto sform : _with_singular_form) | ||
| 1309 | { | ||
| 1310 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SFORM"), sform.c_str(), sform.size(), SQLITE_STATIC); | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | for (auto hyponym : _hypernym_of.inorder_flatten()) | ||
| 1314 | { | ||
| 1315 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPO"), hyponym._id); | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | for (auto hypernym : _hyponym_of.inorder_flatten()) | ||
| 1319 | { | ||
| 1320 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPER"), hypernym._id); | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | for (auto holonym : _part_meronym_of.inorder_flatten()) | ||
| 1324 | { | ||
| 1325 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PHOLO"), holonym._id); | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | for (auto meronym : _part_holonym_of.inorder_flatten()) | ||
| 1329 | { | ||
| 1330 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PMERO"), meronym._id); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | for (auto holonym : _substance_meronym_of.inorder_flatten()) | ||
| 1334 | { | ||
| 1335 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SHOLO"), holonym._id); | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | for (auto meronym : _substance_holonym_of.inorder_flatten()) | ||
| 1339 | { | ||
| 1340 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SMERO"), meronym._id); | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | for (auto holonym : _member_meronym_of.inorder_flatten()) | ||
| 1344 | { | ||
| 1345 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MHOLO"), holonym._id); | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | for (auto meronym : _member_holonym_of.inorder_flatten()) | ||
| 1349 | { | ||
| 1350 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MMERO"), meronym._id); | ||
| 1351 | } | ||
| 1352 | |||
| 1353 | for (auto cls : _instance_of.inorder_flatten()) | ||
| 1354 | { | ||
| 1355 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@CLSID"), cls._id); | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | for (auto inst : _class_of.inorder_flatten()) | ||
| 1359 | { | ||
| 1360 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@INSID"), inst._id); | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
| 1364 | { | ||
| 1365 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
| 1369 | { | ||
| 1370 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | for (auto pertainym : _anti_pertainym_of.inorder_flatten()) | ||
| 1374 | { | ||
| 1375 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PERID"), pertainym._id); | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | for (auto value : _attribute_of.inorder_flatten()) | ||
| 1379 | { | ||
| 1380 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VALID"), value._id); | ||
| 1381 | } | ||
| 1382 | /* | ||
| 1383 | for (auto adj : _derived_from_adjective) | ||
| 1384 | { | ||
| 1385 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | for (auto adj : _not_derived_from_adjective) | ||
| 1389 | { | ||
| 1390 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | for (auto adv : _derived_from_adverb) | ||
| 1394 | { | ||
| 1395 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | for (auto adv : _not_derived_from_adverb) | ||
| 1399 | { | ||
| 1400 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | for (auto n : _derived_from_noun) | ||
| 1404 | { | ||
| 1405 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | for (auto n : _not_derived_from_noun) | ||
| 1409 | { | ||
| 1410 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
| 1411 | } | ||
| 1412 | */ | ||
| 1413 | std::list<noun> output; | ||
| 1414 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 1415 | { | ||
| 1416 | noun tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
| 1417 | tnc._singular = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
| 1418 | |||
| 1419 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
| 1420 | { | ||
| 1421 | tnc._plural = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | output.push_back(tnc); | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | sqlite3_finalize(ppstmt); | ||
| 1428 | |||
| 1429 | for (auto& noun : output) | ||
| 1430 | { | ||
| 1431 | query = "SELECT pronunciation FROM noun_pronunciations WHERE noun_id = ?"; | ||
| 1432 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 1433 | { | ||
| 1434 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | sqlite3_bind_int(ppstmt, 1, noun._id); | ||
| 1438 | |||
| 1439 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 1440 | { | ||
| 1441 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 1442 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
| 1443 | |||
| 1444 | noun.pronunciations.push_back(phonemes); | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | sqlite3_finalize(ppstmt); | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | return output; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | }; | ||
| 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 @@ | |||
| 1 | #ifndef NOUN_QUERY_H_5DE51DD7 | ||
| 2 | #define NOUN_QUERY_H_5DE51DD7 | ||
| 3 | |||
| 4 | namespace verbly { | ||
| 5 | |||
| 6 | class noun_query { | ||
| 7 | public: | ||
| 8 | noun_query(const data& _data); | ||
| 9 | |||
| 10 | noun_query& limit(int _limit); | ||
| 11 | noun_query& random(); | ||
| 12 | noun_query& except(const noun& _word); | ||
| 13 | noun_query& rhymes_with(const word& _word); | ||
| 14 | noun_query& has_pronunciation(); | ||
| 15 | |||
| 16 | noun_query& with_singular_form(std::string _arg); | ||
| 17 | |||
| 18 | noun_query& is_hypernym(); | ||
| 19 | noun_query& hypernym_of(filter<noun> _f); | ||
| 20 | noun_query& full_hypernym_of(filter<noun> _f); | ||
| 21 | |||
| 22 | noun_query& is_hyponym(); | ||
| 23 | noun_query& hyponym_of(filter<noun> _f); | ||
| 24 | noun_query& full_hyponym_of(filter<noun> _f); | ||
| 25 | |||
| 26 | noun_query& is_part_meronym(); | ||
| 27 | noun_query& part_meronym_of(filter<noun> _f); | ||
| 28 | |||
| 29 | noun_query& is_part_holonym(); | ||
| 30 | noun_query& part_holonym_of(filter<noun> _f); | ||
| 31 | |||
| 32 | noun_query& is_substance_meronym(); | ||
| 33 | noun_query& substance_meronym_of(filter<noun> _f); | ||
| 34 | |||
| 35 | noun_query& is_substance_holonym(); | ||
| 36 | noun_query& substance_holonym_of(filter<noun> _f); | ||
| 37 | |||
| 38 | noun_query& is_member_meronym(); | ||
| 39 | noun_query& member_meronym_of(filter<noun> _f); | ||
| 40 | |||
| 41 | noun_query& is_member_holonym(); | ||
| 42 | noun_query& member_holonym_of(filter<noun> _f); | ||
| 43 | |||
| 44 | noun_query& is_proper(); | ||
| 45 | noun_query& is_not_proper(); | ||
| 46 | |||
| 47 | noun_query& is_instance(); | ||
| 48 | noun_query& instance_of(filter<noun> _f); | ||
| 49 | |||
| 50 | noun_query& is_class(); | ||
| 51 | noun_query& class_of(filter<noun> _f); | ||
| 52 | |||
| 53 | noun_query& has_synonyms(); | ||
| 54 | noun_query& synonym_of(filter<noun> _f); | ||
| 55 | |||
| 56 | noun_query& has_antonyms(); | ||
| 57 | noun_query& antonym_of(filter<noun> _f); | ||
| 58 | |||
| 59 | noun_query& has_pertainym(); | ||
| 60 | noun_query& anti_pertainym_of(filter<adjective> _f); | ||
| 61 | |||
| 62 | noun_query& is_attribute(); | ||
| 63 | noun_query& attribute_of(filter<adjective> _f); | ||
| 64 | |||
| 65 | /* noun_query& derived_from(const word& _w); | ||
| 66 | noun_query& not_derived_from(const word& _w);*/ | ||
| 67 | |||
| 68 | std::list<noun> run() const; | ||
| 69 | |||
| 70 | const static int unlimited = -1; | ||
| 71 | |||
| 72 | private: | ||
| 73 | const data& _data; | ||
| 74 | int _limit = unlimited; | ||
| 75 | bool _random = false; | ||
| 76 | std::list<std::string> _rhymes; | ||
| 77 | std::list<noun> _except; | ||
| 78 | bool _has_prn = false; | ||
| 79 | |||
| 80 | std::list<std::string> _with_singular_form; | ||
| 81 | |||
| 82 | bool _is_hypernym = false; | ||
| 83 | filter<noun> _hypernym_of; | ||
| 84 | filter<noun> _full_hypernym_of; | ||
| 85 | |||
| 86 | bool _is_hyponym = false; | ||
| 87 | filter<noun> _hyponym_of; | ||
| 88 | filter<noun> _full_hyponym_of; | ||
| 89 | |||
| 90 | bool _is_part_meronym = false; | ||
| 91 | filter<noun> _part_meronym_of; | ||
| 92 | |||
| 93 | bool _is_substance_meronym = false; | ||
| 94 | filter<noun> _substance_meronym_of; | ||
| 95 | |||
| 96 | bool _is_member_meronym = false; | ||
| 97 | filter<noun> _member_meronym_of; | ||
| 98 | |||
| 99 | bool _is_part_holonym = false; | ||
| 100 | filter<noun> _part_holonym_of; | ||
| 101 | |||
| 102 | bool _is_substance_holonym = false; | ||
| 103 | filter<noun> _substance_holonym_of; | ||
| 104 | |||
| 105 | bool _is_member_holonym = false; | ||
| 106 | filter<noun> _member_holonym_of; | ||
| 107 | |||
| 108 | bool _is_proper = false; | ||
| 109 | bool _is_not_proper = false; | ||
| 110 | |||
| 111 | bool _is_instance = false; | ||
| 112 | filter<noun> _instance_of; | ||
| 113 | |||
| 114 | bool _is_class = false; | ||
| 115 | filter<noun> _class_of; | ||
| 116 | |||
| 117 | bool _has_synonyms = false; | ||
| 118 | filter<noun> _synonym_of; | ||
| 119 | |||
| 120 | bool _has_antonyms = false; | ||
| 121 | filter<noun> _antonym_of; | ||
| 122 | |||
| 123 | bool _has_pertainym = false; | ||
| 124 | filter<adjective> _anti_pertainym_of; | ||
| 125 | |||
| 126 | bool _is_attribute = false; | ||
| 127 | filter<adjective> _attribute_of; | ||
| 128 | |||
| 129 | /* std::list<adjective> _derived_from_adjective; | ||
| 130 | std::list<adjective> _not_derived_from_adjective; | ||
| 131 | std::list<adverb> _derived_from_adverb; | ||
| 132 | std::list<adverb> _not_derived_from_adverb; | ||
| 133 | std::list<noun> _derived_from_noun; | ||
| 134 | std::list<noun> _not_derived_from_noun;*/ | ||
| 135 | }; | ||
| 136 | |||
| 137 | }; | ||
| 138 | |||
| 139 | #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 @@ | |||
| 1 | #include "verbly.h" | ||
| 2 | |||
| 3 | namespace verbly { | ||
| 4 | |||
| 5 | std::string preposition::get_form() const | ||
| 6 | { | ||
| 7 | return form; | ||
| 8 | } | ||
| 9 | |||
| 10 | preposition_query::preposition_query(const data& _data) : _data(_data) | ||
| 11 | { | ||
| 12 | |||
| 13 | } | ||
| 14 | |||
| 15 | preposition_query& preposition_query::limit(int _limit) | ||
| 16 | { | ||
| 17 | this->_limit = _limit; | ||
| 18 | |||
| 19 | return *this; | ||
| 20 | } | ||
| 21 | |||
| 22 | preposition_query& preposition_query::random() | ||
| 23 | { | ||
| 24 | _random = true; | ||
| 25 | |||
| 26 | return *this; | ||
| 27 | } | ||
| 28 | |||
| 29 | preposition_query& preposition_query::in_group(std::string _arg) | ||
| 30 | { | ||
| 31 | _in_group.push_back(_arg); | ||
| 32 | |||
| 33 | return *this; | ||
| 34 | } | ||
| 35 | |||
| 36 | std::list<preposition> preposition_query::run() const | ||
| 37 | { | ||
| 38 | std::stringstream construct; | ||
| 39 | construct << "SELECT form FROM prepositions"; | ||
| 40 | |||
| 41 | if (!_in_group.empty()) | ||
| 42 | { | ||
| 43 | std::list<std::string> clauses(_in_group.size(), "groupname = @GNAME"); | ||
| 44 | construct << " WHERE preposition_id IN (SELECT preposition_id FROM preposition_groups WHERE "; | ||
| 45 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); | ||
| 46 | construct << ")"; | ||
| 47 | } | ||
| 48 | |||
| 49 | if (_random) | ||
| 50 | { | ||
| 51 | construct << " ORDER BY RANDOM()"; | ||
| 52 | } | ||
| 53 | |||
| 54 | if (_limit != unlimited) | ||
| 55 | { | ||
| 56 | construct << " LIMIT " << _limit; | ||
| 57 | } | ||
| 58 | |||
| 59 | sqlite3_stmt* ppstmt; | ||
| 60 | std::string query = construct.str(); | ||
| 61 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 62 | { | ||
| 63 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 64 | } | ||
| 65 | |||
| 66 | for (auto& group : _in_group) | ||
| 67 | { | ||
| 68 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GNAME"), group.c_str(), group.length(), SQLITE_STATIC); | ||
| 69 | } | ||
| 70 | |||
| 71 | std::list<preposition> output; | ||
| 72 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 73 | { | ||
| 74 | preposition pp; | ||
| 75 | pp.form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 76 | |||
| 77 | output.push_back(pp); | ||
| 78 | } | ||
| 79 | |||
| 80 | return output; | ||
| 81 | } | ||
| 82 | |||
| 83 | }; | ||
| 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 @@ | |||
| 1 | #ifndef PREPOSITION_H_FF908021 | ||
| 2 | #define PREPOSITION_H_FF908021 | ||
| 3 | |||
| 4 | namespace verbly { | ||
| 5 | |||
| 6 | class preposition_query; | ||
| 7 | |||
| 8 | class preposition { | ||
| 9 | public: | ||
| 10 | std::string get_form() const; | ||
| 11 | |||
| 12 | private: | ||
| 13 | friend class preposition_query; | ||
| 14 | |||
| 15 | std::string form; | ||
| 16 | }; | ||
| 17 | |||
| 18 | class preposition_query { | ||
| 19 | public: | ||
| 20 | preposition_query(const data& _data); | ||
| 21 | |||
| 22 | preposition_query& limit(int _limit); | ||
| 23 | preposition_query& random(); | ||
| 24 | preposition_query& in_group(std::string _arg); | ||
| 25 | |||
| 26 | std::list<preposition> run() const; | ||
| 27 | |||
| 28 | const static int unlimited = -1; | ||
| 29 | private: | ||
| 30 | const data& _data; | ||
| 31 | int _limit = unlimited; | ||
| 32 | bool _random = false; | ||
| 33 | std::list<std::string> _in_group; | ||
| 34 | }; | ||
| 35 | |||
| 36 | }; | ||
| 37 | |||
| 38 | #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 @@ | |||
| 2 | 2 | ||
| 3 | namespace verbly { | 3 | namespace verbly { |
| 4 | 4 | ||
| 5 | token::token(token::type _type) : _type(_type) | 5 | token::type token::get_type() const |
| 6 | { | 6 | { |
| 7 | 7 | return _type; | |
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | token::type token::token_type() const | 10 | int token::get_extra() const |
| 11 | { | 11 | { |
| 12 | return _type; | 12 | return _extra; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | verb_token::verb_token(const verb& _verb) : token(token::type::verb), _verb(&_verb) | 15 | void token::set_extra(int _arg) |
| 16 | { | 16 | { |
| 17 | 17 | _extra = _arg; | |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | const verb& verb_token::get_verb() const | 20 | token::token(const token& other) |
| 21 | { | 21 | { |
| 22 | return *_verb; | 22 | _type = other._type; |
| 23 | |||
| 24 | switch (_type) | ||
| 25 | { | ||
| 26 | case token::type::verb: | ||
| 27 | { | ||
| 28 | new(&_verb._verb) verb(other._verb._verb); | ||
| 29 | _verb._infl = other._verb._infl; | ||
| 30 | |||
| 31 | break; | ||
| 32 | } | ||
| 33 | |||
| 34 | case token::type::noun: | ||
| 35 | { | ||
| 36 | new(&_noun._noun) noun(other._noun._noun); | ||
| 37 | _noun._infl = other._noun._infl; | ||
| 38 | |||
| 39 | break; | ||
| 40 | } | ||
| 41 | |||
| 42 | case token::type::adjective: | ||
| 43 | { | ||
| 44 | new(&_adjective._adjective) adjective(other._adjective._adjective); | ||
| 45 | _adjective._infl = other._adjective._infl; | ||
| 46 | |||
| 47 | break; | ||
| 48 | } | ||
| 49 | |||
| 50 | case token::type::adverb: | ||
| 51 | { | ||
| 52 | new(&_adverb._adverb) adverb(other._adverb._adverb); | ||
| 53 | _adverb._infl = other._adverb._infl; | ||
| 54 | |||
| 55 | break; | ||
| 56 | } | ||
| 57 | |||
| 58 | case token::type::preposition: | ||
| 59 | { | ||
| 60 | new(&_preposition._preposition) preposition(other._preposition._preposition); | ||
| 61 | |||
| 62 | break; | ||
| 63 | } | ||
| 64 | |||
| 65 | case token::type::fillin: | ||
| 66 | { | ||
| 67 | _fillin._type = other._fillin._type; | ||
| 68 | |||
| 69 | break; | ||
| 70 | } | ||
| 71 | |||
| 72 | case token::type::string: | ||
| 73 | { | ||
| 74 | new(&_string._str) std::string(other._string._str); | ||
| 75 | |||
| 76 | break; | ||
| 77 | } | ||
| 78 | |||
| 79 | case token::type::utterance: | ||
| 80 | { | ||
| 81 | new(&_utterance._utterance) std::list<token>(other._utterance._utterance); | ||
| 82 | |||
| 83 | break; | ||
| 84 | } | ||
| 85 | } | ||
| 23 | } | 86 | } |
| 24 | 87 | ||
| 25 | verb_token& verb_token::inflect(verb_token::inflection infl) | 88 | token& token::operator=(const token& other) |
| 26 | { | 89 | { |
| 27 | _inflection = infl; | 90 | this->~token(); |
| 91 | |||
| 92 | _type = other._type; | ||
| 93 | |||
| 94 | switch (_type) | ||
| 95 | { | ||
| 96 | case token::type::verb: | ||
| 97 | { | ||
| 98 | new(&_verb._verb) verb(other._verb._verb); | ||
| 99 | _verb._infl = other._verb._infl; | ||
| 100 | |||
| 101 | break; | ||
| 102 | } | ||
| 103 | |||
| 104 | case token::type::noun: | ||
| 105 | { | ||
| 106 | new(&_noun._noun) noun(other._noun._noun); | ||
| 107 | _noun._infl = other._noun._infl; | ||
| 108 | |||
| 109 | break; | ||
| 110 | } | ||
| 111 | |||
| 112 | case token::type::adjective: | ||
| 113 | { | ||
| 114 | new(&_adjective._adjective) adjective(other._adjective._adjective); | ||
| 115 | _adjective._infl = other._adjective._infl; | ||
| 116 | |||
| 117 | break; | ||
| 118 | } | ||
| 119 | |||
| 120 | case token::type::adverb: | ||
| 121 | { | ||
| 122 | new(&_adverb._adverb) adverb(other._adverb._adverb); | ||
| 123 | _adverb._infl = other._adverb._infl; | ||
| 124 | |||
| 125 | break; | ||
| 126 | } | ||
| 127 | |||
| 128 | case token::type::preposition: | ||
| 129 | { | ||
| 130 | new(&_preposition._preposition) preposition(other._preposition._preposition); | ||
| 131 | |||
| 132 | break; | ||
| 133 | } | ||
| 134 | |||
| 135 | case token::type::fillin: | ||
| 136 | { | ||
| 137 | _fillin._type = other._fillin._type; | ||
| 138 | |||
| 139 | break; | ||
| 140 | } | ||
| 141 | |||
| 142 | case token::type::string: | ||
| 143 | { | ||
| 144 | new(&_string._str) std::string(other._string._str); | ||
| 145 | |||
| 146 | break; | ||
| 147 | } | ||
| 148 | |||
| 149 | case token::type::utterance: | ||
| 150 | { | ||
| 151 | new(&_utterance._utterance) std::list<token>(other._utterance._utterance); | ||
| 152 | |||
| 153 | break; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 28 | return *this; | 157 | return *this; |
| 29 | } | 158 | } |
| 30 | 159 | ||
| 31 | bool verb_token::complete() const | 160 | token::~token() |
| 32 | { | 161 | { |
| 33 | return true; | 162 | switch (_type) |
| 163 | { | ||
| 164 | case token::type::verb: | ||
| 165 | { | ||
| 166 | _verb._verb.~verb(); | ||
| 167 | |||
| 168 | break; | ||
| 169 | } | ||
| 170 | |||
| 171 | case token::type::noun: | ||
| 172 | { | ||
| 173 | _noun._noun.~noun(); | ||
| 174 | |||
| 175 | break; | ||
| 176 | } | ||
| 177 | |||
| 178 | case token::type::adjective: | ||
| 179 | { | ||
| 180 | _adjective._adjective.~adjective(); | ||
| 181 | |||
| 182 | break; | ||
| 183 | } | ||
| 184 | |||
| 185 | case token::type::adverb: | ||
| 186 | { | ||
| 187 | _adverb._adverb.~adverb(); | ||
| 188 | |||
| 189 | break; | ||
| 190 | } | ||
| 191 | |||
| 192 | case token::type::preposition: | ||
| 193 | { | ||
| 194 | _preposition._preposition.~preposition(); | ||
| 195 | |||
| 196 | break; | ||
| 197 | } | ||
| 198 | |||
| 199 | case token::type::fillin: | ||
| 200 | { | ||
| 201 | // Nothing! | ||
| 202 | |||
| 203 | break; | ||
| 204 | } | ||
| 205 | |||
| 206 | case token::type::string: | ||
| 207 | { | ||
| 208 | using string_type = std::string; | ||
| 209 | _string._str.~string_type(); | ||
| 210 | |||
| 211 | break; | ||
| 212 | } | ||
| 213 | |||
| 214 | case token::type::utterance: | ||
| 215 | { | ||
| 216 | using list_type = std::list<token>; | ||
| 217 | _utterance._utterance.~list_type(); | ||
| 218 | |||
| 219 | break; | ||
| 220 | } | ||
| 221 | } | ||
| 34 | } | 222 | } |
| 35 | 223 | ||
| 36 | std::string verb_token::compile() const | 224 | bool token::is_complete() const |
| 37 | { | 225 | { |
| 38 | switch (_inflection) | 226 | if (_type == token::type::utterance) |
| 39 | { | 227 | { |
| 40 | case inflection::infinitive: return _verb->infinitive_form(); | 228 | return std::all_of(std::begin(_utterance._utterance), std::end(_utterance._utterance), [] (const token& tkn) { |
| 41 | case inflection::past_tense: return _verb->past_tense_form(); | 229 | return tkn.is_complete(); |
| 42 | case inflection::past_participle: return _verb->past_participle_form(); | 230 | }); |
| 43 | case inflection::ing_form: return _verb->ing_form(); | 231 | } else if (_type == token::type::fillin) |
| 44 | case inflection::s_form: return _verb->s_form(); | 232 | { |
| 233 | return false; | ||
| 234 | } else { | ||
| 235 | return true; | ||
| 45 | } | 236 | } |
| 46 | } | 237 | } |
| 47 | 238 | ||
| 48 | token* verb_token::copy() const | 239 | std::string token::compile() const |
| 240 | { | ||
| 241 | switch (_type) | ||
| 242 | { | ||
| 243 | case token::type::verb: | ||
| 244 | { | ||
| 245 | switch (_verb._infl) | ||
| 246 | { | ||
| 247 | case token::verb_inflection::infinitive: return _verb._verb.infinitive_form(); | ||
| 248 | case token::verb_inflection::past_tense: return _verb._verb.past_tense_form(); | ||
| 249 | case token::verb_inflection::past_participle: return _verb._verb.past_participle_form(); | ||
| 250 | case token::verb_inflection::ing_form: return _verb._verb.ing_form(); | ||
| 251 | case token::verb_inflection::s_form: return _verb._verb.s_form(); | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | case token::type::noun: | ||
| 256 | { | ||
| 257 | switch (_noun._infl) | ||
| 258 | { | ||
| 259 | case token::noun_inflection::singular: return _noun._noun.singular_form(); | ||
| 260 | case token::noun_inflection::plural: return _noun._noun.plural_form(); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | case token::type::adjective: | ||
| 265 | { | ||
| 266 | switch (_adjective._infl) | ||
| 267 | { | ||
| 268 | case token::adjective_inflection::base: return _adjective._adjective.base_form(); | ||
| 269 | case token::adjective_inflection::comparative: return _adjective._adjective.comparative_form(); | ||
| 270 | case token::adjective_inflection::superlative: return _adjective._adjective.superlative_form(); | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | case token::type::adverb: | ||
| 275 | { | ||
| 276 | switch (_adverb._infl) | ||
| 277 | { | ||
| 278 | case token::adverb_inflection::base: return _adverb._adverb.base_form(); | ||
| 279 | case token::adverb_inflection::comparative: return _adverb._adverb.comparative_form(); | ||
| 280 | case token::adverb_inflection::superlative: return _adverb._adverb.superlative_form(); | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | case token::type::preposition: return _preposition._preposition.get_form(); | ||
| 285 | case token::type::string: return _string._str; | ||
| 286 | |||
| 287 | case token::type::fillin: | ||
| 288 | { | ||
| 289 | throw std::runtime_error("Cannot compile a fillin token."); | ||
| 290 | } | ||
| 291 | |||
| 292 | case token::type::utterance: | ||
| 293 | { | ||
| 294 | std::list<std::string> compiled; | ||
| 295 | std::transform(std::begin(_utterance._utterance), std::end(_utterance._utterance), std::back_inserter(compiled), [] (token tkn) { | ||
| 296 | return tkn.compile(); | ||
| 297 | }); | ||
| 298 | |||
| 299 | return verbly::implode(std::begin(compiled), std::end(compiled), " "); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | token::token(verb _verb) : _type(type::verb) | ||
| 305 | { | ||
| 306 | new(&this->_verb._verb) verb(_verb); | ||
| 307 | this->_verb._infl = verb_inflection::infinitive; | ||
| 308 | } | ||
| 309 | |||
| 310 | token::token(verb _verb, verb_inflection _infl) : token(_verb) | ||
| 311 | { | ||
| 312 | this->_verb._infl = _infl; | ||
| 313 | } | ||
| 314 | |||
| 315 | token& token::operator=(verb _verb) | ||
| 316 | { | ||
| 317 | *this = token{_verb}; | ||
| 318 | |||
| 319 | return *this; | ||
| 320 | } | ||
| 321 | |||
| 322 | verb token::get_verb() const | ||
| 323 | { | ||
| 324 | assert(_type == type::verb); | ||
| 325 | |||
| 326 | return _verb._verb; | ||
| 327 | } | ||
| 328 | |||
| 329 | void token::set_verb(verb _verb) | ||
| 330 | { | ||
| 331 | assert(_type == type::verb); | ||
| 332 | |||
| 333 | this->_verb._verb = _verb; | ||
| 334 | } | ||
| 335 | |||
| 336 | token::verb_inflection token::get_verb_inflection() const | ||
| 337 | { | ||
| 338 | assert(_type == type::verb); | ||
| 339 | |||
| 340 | return _verb._infl; | ||
| 341 | } | ||
| 342 | |||
| 343 | void token::set_verb_inflection(verb_inflection _infl) | ||
| 344 | { | ||
| 345 | assert(_type == type::verb); | ||
| 346 | |||
| 347 | _verb._infl = _infl; | ||
| 348 | } | ||
| 349 | |||
| 350 | token::token(noun _noun) : _type(type::noun) | ||
| 351 | { | ||
| 352 | new(&this->_noun._noun) noun(_noun); | ||
| 353 | this->_noun._infl = noun_inflection::singular; | ||
| 354 | } | ||
| 355 | |||
| 356 | token::token(noun _noun, noun_inflection _infl) : token(_noun) | ||
| 357 | { | ||
| 358 | this->_noun._infl = _infl; | ||
| 359 | } | ||
| 360 | |||
| 361 | token& token::operator=(noun _noun) | ||
| 49 | { | 362 | { |
| 50 | return new verb_token(*this); | 363 | *this = token{_noun}; |
| 364 | |||
| 365 | return *this; | ||
| 366 | } | ||
| 367 | |||
| 368 | noun token::get_noun() const | ||
| 369 | { | ||
| 370 | assert(_type == type::noun); | ||
| 371 | |||
| 372 | return _noun._noun; | ||
| 373 | } | ||
| 374 | |||
| 375 | void token::set_noun(noun _noun) | ||
| 376 | { | ||
| 377 | assert(_type == type::noun); | ||
| 378 | |||
| 379 | this->_noun._noun = _noun; | ||
| 380 | } | ||
| 381 | |||
| 382 | token::noun_inflection token::get_noun_inflection() const | ||
| 383 | { | ||
| 384 | assert(_type == type::noun); | ||
| 385 | |||
| 386 | return _noun._infl; | ||
| 387 | } | ||
| 388 | |||
| 389 | void token::set_noun_inflection(noun_inflection _infl) | ||
| 390 | { | ||
| 391 | assert(_type == type::noun); | ||
| 392 | |||
| 393 | _noun._infl = _infl; | ||
| 394 | } | ||
| 395 | |||
| 396 | token::token(adjective _adjective) : _type(type::adjective) | ||
| 397 | { | ||
| 398 | new(&this->_adjective._adjective) adjective(_adjective); | ||
| 399 | this->_adjective._infl = adjective_inflection::base; | ||
| 400 | } | ||
| 401 | |||
| 402 | token::token(adjective _adjective, adjective_inflection _infl) : token(_adjective) | ||
| 403 | { | ||
| 404 | this->_adjective._infl = _infl; | ||
| 405 | } | ||
| 406 | |||
| 407 | token& token::operator=(adjective _adjective) | ||
| 408 | { | ||
| 409 | *this = token{_adjective}; | ||
| 410 | |||
| 411 | return *this; | ||
| 412 | } | ||
| 413 | |||
| 414 | adjective token::get_adjective() const | ||
| 415 | { | ||
| 416 | assert(_type == type::adjective); | ||
| 417 | |||
| 418 | return _adjective._adjective; | ||
| 419 | } | ||
| 420 | |||
| 421 | void token::set_adjective(adjective _adjective) | ||
| 422 | { | ||
| 423 | assert(_type == type::adjective); | ||
| 424 | |||
| 425 | this->_adjective._adjective = _adjective; | ||
| 426 | } | ||
| 427 | |||
| 428 | token::adjective_inflection token::get_adjective_inflection() const | ||
| 429 | { | ||
| 430 | assert(_type == type::adjective); | ||
| 431 | |||
| 432 | return _adjective._infl; | ||
| 433 | } | ||
| 434 | |||
| 435 | void token::set_adjective_inflection(adjective_inflection _infl) | ||
| 436 | { | ||
| 437 | assert(_type == type::adjective); | ||
| 438 | |||
| 439 | _adjective._infl = _infl; | ||
| 440 | } | ||
| 441 | |||
| 442 | token::token(adverb _adverb) : _type(type::adverb) | ||
| 443 | { | ||
| 444 | new(&this->_adverb._adverb) adverb(_adverb); | ||
| 445 | this->_adverb._infl = adverb_inflection::base; | ||
| 446 | } | ||
| 447 | |||
| 448 | token::token(adverb _adverb, adverb_inflection _infl) : token(_adverb) | ||
| 449 | { | ||
| 450 | this->_adverb._infl = _infl; | ||
| 451 | } | ||
| 452 | |||
| 453 | token& token::operator=(adverb _adverb) | ||
| 454 | { | ||
| 455 | *this = token{_adverb}; | ||
| 456 | |||
| 457 | return *this; | ||
| 458 | } | ||
| 459 | |||
| 460 | adverb token::get_adverb() const | ||
| 461 | { | ||
| 462 | assert(_type == type::adverb); | ||
| 463 | |||
| 464 | return _adverb._adverb; | ||
| 465 | } | ||
| 466 | |||
| 467 | void token::set_adverb(adverb _adverb) | ||
| 468 | { | ||
| 469 | assert(_type == type::adverb); | ||
| 470 | |||
| 471 | this->_adverb._adverb = _adverb; | ||
| 472 | } | ||
| 473 | |||
| 474 | token::adverb_inflection token::get_adverb_inflection() const | ||
| 475 | { | ||
| 476 | assert(_type == type::adverb); | ||
| 477 | |||
| 478 | return _adverb._infl; | ||
| 479 | } | ||
| 480 | |||
| 481 | void token::set_adverb_inflection(adverb_inflection _infl) | ||
| 482 | { | ||
| 483 | assert(_type == type::adverb); | ||
| 484 | |||
| 485 | _adverb._infl = _infl; | ||
| 486 | } | ||
| 487 | |||
| 488 | token::token(preposition _preposition) : _type(type::preposition) | ||
| 489 | { | ||
| 490 | new(&this->_preposition._preposition) preposition(_preposition); | ||
| 491 | } | ||
| 492 | |||
| 493 | token& token::operator=(preposition _preposition) | ||
| 494 | { | ||
| 495 | *this = token{_preposition}; | ||
| 496 | |||
| 497 | return *this; | ||
| 498 | } | ||
| 499 | |||
| 500 | preposition token::get_preposition() const | ||
| 501 | { | ||
| 502 | assert(_type == type::preposition); | ||
| 503 | |||
| 504 | return _preposition._preposition; | ||
| 505 | } | ||
| 506 | |||
| 507 | void token::set_preposition(preposition _preposition) | ||
| 508 | { | ||
| 509 | assert(_type == type::preposition); | ||
| 510 | |||
| 511 | this->_preposition._preposition = _preposition; | ||
| 512 | } | ||
| 513 | |||
| 514 | token::token(fillin_type _ft) : _type(type::fillin) | ||
| 515 | { | ||
| 516 | _fillin._type = _ft; | ||
| 517 | } | ||
| 518 | |||
| 519 | token& token::operator=(fillin_type _ft) | ||
| 520 | { | ||
| 521 | *this = token{_ft}; | ||
| 522 | |||
| 523 | return *this; | ||
| 524 | } | ||
| 525 | |||
| 526 | token::fillin_type token::get_fillin_type() const | ||
| 527 | { | ||
| 528 | assert(_type == type::fillin); | ||
| 529 | |||
| 530 | return _fillin._type; | ||
| 531 | } | ||
| 532 | |||
| 533 | void token::set_fillin_type(fillin_type _ft) | ||
| 534 | { | ||
| 535 | assert(_type == type::fillin); | ||
| 536 | |||
| 537 | _fillin._type = _ft; | ||
| 538 | } | ||
| 539 | |||
| 540 | token::token() : _type(type::utterance) | ||
| 541 | { | ||
| 542 | new(&_utterance._utterance) std::list<token>(); | ||
| 543 | } | ||
| 544 | |||
| 545 | token::token(std::initializer_list<token> _init) : _type(type::utterance) | ||
| 546 | { | ||
| 547 | new(&_utterance._utterance) std::list<token>(_init); | ||
| 548 | } | ||
| 549 | |||
| 550 | token::iterator token::begin() | ||
| 551 | { | ||
| 552 | assert(_type == type::utterance); | ||
| 553 | |||
| 554 | return _utterance._utterance.begin(); | ||
| 555 | } | ||
| 556 | |||
| 557 | token::iterator token::end() | ||
| 558 | { | ||
| 559 | assert(_type == type::utterance); | ||
| 560 | |||
| 561 | return _utterance._utterance.end(); | ||
| 562 | } | ||
| 563 | |||
| 564 | token& token::operator<<(token _tkn) | ||
| 565 | { | ||
| 566 | assert(_type == type::utterance); | ||
| 567 | |||
| 568 | _utterance._utterance.push_back(_tkn); | ||
| 569 | |||
| 570 | return *this; | ||
| 571 | } | ||
| 572 | |||
| 573 | void token::push_back(token _tkn) | ||
| 574 | { | ||
| 575 | assert(_type == type::utterance); | ||
| 576 | |||
| 577 | _utterance._utterance.push_back(_tkn); | ||
| 578 | } | ||
| 579 | |||
| 580 | void token::insert(iterator before, token _tkn) | ||
| 581 | { | ||
| 582 | assert(_type == type::utterance); | ||
| 583 | |||
| 584 | _utterance._utterance.insert(before, _tkn); | ||
| 585 | } | ||
| 586 | |||
| 587 | void token::replace(iterator torepl, token _tkn) | ||
| 588 | { | ||
| 589 | assert(_type == type::utterance); | ||
| 590 | |||
| 591 | _utterance._utterance.insert(torepl, _tkn); | ||
| 592 | _utterance._utterance.erase(torepl); | ||
| 593 | } | ||
| 594 | |||
| 595 | void token::erase(iterator toer) | ||
| 596 | { | ||
| 597 | assert(_type == type::utterance); | ||
| 598 | |||
| 599 | _utterance._utterance.erase(toer); | ||
| 600 | } | ||
| 601 | |||
| 602 | token::token(std::string _str) : _type(type::string) | ||
| 603 | { | ||
| 604 | new(&_string._str) std::string(_str); | ||
| 605 | } | ||
| 606 | |||
| 607 | token& token::operator=(std::string _str) | ||
| 608 | { | ||
| 609 | *this = token{_str}; | ||
| 610 | |||
| 611 | return *this; | ||
| 612 | } | ||
| 613 | |||
| 614 | std::string token::get_string() const | ||
| 615 | { | ||
| 616 | assert(_type == type::string); | ||
| 617 | |||
| 618 | return _string._str; | ||
| 619 | } | ||
| 620 | |||
| 621 | void token::set_string(std::string _str) | ||
| 622 | { | ||
| 623 | assert(_type == type::string); | ||
| 624 | |||
| 625 | _string._str = _str; | ||
| 51 | } | 626 | } |
| 52 | 627 | ||
| 53 | }; | 628 | }; |
| 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 @@ | |||
| 1 | #ifndef TOKEN_H_AD62C505 | 1 | #ifndef TOKEN_H_AD62C505 |
| 2 | #define TOKEN_H_AD62C505 | 2 | #define TOKEN_H_AD62C505 |
| 3 | 3 | ||
| 4 | #include <string> | ||
| 5 | #include <list> | ||
| 6 | #include <sstream> | ||
| 7 | #include <algorithm> | ||
| 8 | |||
| 9 | namespace verbly { | 4 | namespace verbly { |
| 10 | 5 | ||
| 11 | class verb; | ||
| 12 | |||
| 13 | class selrestr { | ||
| 14 | }; | ||
| 15 | |||
| 16 | class synrestr { | ||
| 17 | }; | ||
| 18 | |||
| 19 | enum class fillin_type { | ||
| 20 | noun_phrase, | ||
| 21 | participle_phrase, | ||
| 22 | adjective, | ||
| 23 | adverb | ||
| 24 | }; | ||
| 25 | |||
| 26 | class token { | 6 | class token { |
| 27 | public: | 7 | public: |
| 28 | enum class type { | 8 | enum class type { |
| 29 | verb, | 9 | verb, |
| 10 | noun, | ||
| 11 | adjective, | ||
| 12 | adverb, | ||
| 13 | preposition, | ||
| 30 | fillin, | 14 | fillin, |
| 31 | string, | 15 | utterance, |
| 32 | utterance | 16 | string |
| 33 | }; | 17 | }; |
| 34 | 18 | ||
| 35 | protected: | 19 | enum class verb_inflection { |
| 36 | // General | ||
| 37 | type _type; | ||
| 38 | |||
| 39 | token(type _type); | ||
| 40 | |||
| 41 | public: | ||
| 42 | enum type token_type() const; | ||
| 43 | |||
| 44 | virtual bool complete() const = 0; | ||
| 45 | virtual std::string compile() const = 0; | ||
| 46 | virtual token* copy() const = 0; | ||
| 47 | }; | ||
| 48 | |||
| 49 | class verb_token : public token { | ||
| 50 | public: | ||
| 51 | enum class inflection { | ||
| 52 | infinitive, | 20 | infinitive, |
| 53 | past_tense, | 21 | past_tense, |
| 54 | past_participle, | 22 | past_participle, |
| 55 | ing_form, | 23 | s_form, |
| 56 | s_form | 24 | ing_form |
| 57 | }; | 25 | }; |
| 58 | 26 | ||
| 59 | private: | 27 | enum class noun_inflection { |
| 60 | // Verb | 28 | singular, |
| 61 | const verb* _verb; | 29 | plural |
| 62 | inflection _inflection = inflection::infinitive; | 30 | }; |
| 63 | |||
| 64 | public: | ||
| 65 | verb_token(const verb& _verb); | ||
| 66 | |||
| 67 | const verb& get_verb() const; | ||
| 68 | |||
| 69 | verb_token& inflect(inflection infl); | ||
| 70 | |||
| 71 | bool complete() const; | ||
| 72 | |||
| 73 | std::string compile() const; | ||
| 74 | |||
| 75 | token* copy() const; | ||
| 76 | }; | ||
| 77 | |||
| 78 | class utterance_token : public token { | ||
| 79 | private: | ||
| 80 | // Utterance | ||
| 81 | std::list<std::unique_ptr<token>> utterance; | ||
| 82 | |||
| 83 | public: | ||
| 84 | typedef std::list<std::unique_ptr<token>>::iterator iterator; | ||
| 85 | /*class iterator { | ||
| 86 | private: | ||
| 87 | friend class utterance_token; | ||
| 88 | |||
| 89 | std::list<std::unique_ptr<token>>::iterator it; | ||
| 90 | |||
| 91 | public: | ||
| 92 | iterator(std::list<std::unique_ptr<token>>::iterator it) : it(it) | ||
| 93 | { | ||
| 94 | |||
| 95 | } | ||
| 96 | |||
| 97 | iterator& operator++() | ||
| 98 | { | ||
| 99 | ++it; | ||
| 100 | return *this; | ||
| 101 | } | ||
| 102 | |||
| 103 | iterator& operator--() | ||
| 104 | { | ||
| 105 | --it; | ||
| 106 | return *this; | ||
| 107 | } | ||
| 108 | |||
| 109 | bool operator==(const iterator& other) const | ||
| 110 | { | ||
| 111 | return it == other.it; | ||
| 112 | } | ||
| 113 | |||
| 114 | bool operator!=(const iterator& other) const | ||
| 115 | { | ||
| 116 | return it != other.it; | ||
| 117 | } | ||
| 118 | |||
| 119 | token& operator*() | ||
| 120 | { | ||
| 121 | return **it; | ||
| 122 | } | ||
| 123 | |||
| 124 | token& operator->() | ||
| 125 | { | ||
| 126 | return **it; | ||
| 127 | } | ||
| 128 | };*/ | ||
| 129 | |||
| 130 | utterance_token(std::initializer_list<token*> tkns) : token(token::type::utterance) | ||
| 131 | { | ||
| 132 | for (auto tkn : tkns) | ||
| 133 | { | ||
| 134 | utterance.push_back(std::unique_ptr<token>(tkn)); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | utterance_token(const utterance_token& other) : token(token::type::utterance) | ||
| 139 | { | ||
| 140 | for (auto& tkn : other.utterance) | ||
| 141 | { | ||
| 142 | utterance.push_back(std::unique_ptr<token>(tkn->copy())); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | 31 | ||
| 146 | utterance_token(utterance_token&& other) : token(token::type::utterance), utterance(std::move(other.utterance)) | 32 | enum class adjective_inflection { |
| 147 | { | 33 | base, |
| 148 | 34 | comparative, | |
| 149 | } | 35 | superlative |
| 36 | }; | ||
| 150 | 37 | ||
| 151 | utterance_token& operator=(const utterance_token& other) | 38 | enum class adverb_inflection { |
| 152 | { | 39 | base, |
| 153 | utterance.clear(); | 40 | comparative, |
| 154 | 41 | superlative | |
| 155 | for (auto& tkn : other.utterance) | 42 | }; |
| 156 | { | ||
| 157 | utterance.push_back(std::unique_ptr<token>(tkn->copy())); | ||
| 158 | } | ||
| 159 | |||
| 160 | return *this; | ||
| 161 | } | ||
| 162 | 43 | ||
| 163 | utterance_token& operator=(utterance_token&& other) | 44 | enum class fillin_type { |
| 164 | { | 45 | generic, |
| 165 | utterance = std::move(other.utterance); | 46 | noun_phrase, |
| 166 | 47 | adjective_phrase, | |
| 167 | return *this; | 48 | adverb_phrase, |
| 168 | } | 49 | participle_phrase, |
| 50 | infinitive_phrase | ||
| 51 | }; | ||
| 169 | 52 | ||
| 170 | iterator begin() | 53 | type get_type() const; |
| 171 | { | ||
| 172 | return std::begin(utterance); | ||
| 173 | } | ||
| 174 | 54 | ||
| 175 | iterator end() | 55 | int get_extra() const; |
| 176 | { | 56 | void set_extra(int _arg); |
| 177 | return std::end(utterance); | ||
| 178 | } | ||
| 179 | 57 | ||
| 180 | void erase(iterator it) | 58 | token(const token& other); |
| 181 | { | 59 | token& operator=(const token& other); |
| 182 | utterance.erase(it); | 60 | ~token(); |
| 183 | } | ||
| 184 | 61 | ||
| 185 | bool complete() const | 62 | bool is_complete() const; |
| 186 | { | 63 | std::string compile() const; |
| 187 | return std::all_of(std::begin(utterance), std::end(utterance), [] (const std::unique_ptr<token>& tkn) { | ||
| 188 | return tkn->complete(); | ||
| 189 | }); | ||
| 190 | } | ||
| 191 | 64 | ||
| 192 | std::string compile() const | 65 | // Verb |
| 193 | { | 66 | token(verb _verb); |
| 194 | std::stringstream result; | 67 | token(verb _verb, verb_inflection _infl); |
| 195 | for (auto& t : utterance) | 68 | token& operator=(verb _verb); |
| 196 | { | 69 | verb get_verb() const; |
| 197 | if (t->complete()) | 70 | void set_verb(verb _verb); |
| 198 | { | 71 | verb_inflection get_verb_inflection() const; |
| 199 | result << t->compile() << " "; | 72 | void set_verb_inflection(verb_inflection _infl); |
| 200 | } else { | 73 | |
| 201 | return "Could not compile!"; | 74 | // Noun |
| 202 | } | 75 | token(noun _noun); |
| 203 | } | 76 | token(noun _noun, noun_inflection _infl); |
| 204 | 77 | token& operator=(noun _noun); | |
| 205 | std::string output = result.str(); | 78 | noun get_noun() const; |
| 206 | if (output != "") | 79 | void set_noun(noun _noun); |
| 207 | { | 80 | noun_inflection get_noun_inflection() const; |
| 208 | output.pop_back(); | 81 | void set_noun_inflection(noun_inflection _infl); |
| 209 | } | 82 | |
| 210 | 83 | // Adjective | |
| 211 | return output; | 84 | token(adjective _adjective); |
| 212 | } | 85 | token(adjective _adjective, adjective_inflection _infl); |
| 86 | token& operator=(adjective _adjective); | ||
| 87 | adjective get_adjective() const; | ||
| 88 | void set_adjective(adjective _adjective); | ||
| 89 | adjective_inflection get_adjective_inflection() const; | ||
| 90 | void set_adjective_inflection(adjective_inflection _infl); | ||
| 91 | |||
| 92 | // Adverb | ||
| 93 | token(adverb _adverb); | ||
| 94 | token(adverb _adverb, adverb_inflection _infl); | ||
| 95 | token& operator=(adverb _adverb); | ||
| 96 | adverb get_adverb() const; | ||
| 97 | void set_adverb(adverb _adverb); | ||
| 98 | adverb_inflection get_adverb_inflection() const; | ||
| 99 | void set_adverb_inflection(adverb_inflection _infl); | ||
| 100 | |||
| 101 | // Preposition | ||
| 102 | token(preposition _preposition); | ||
| 103 | token& operator=(preposition _preposition); | ||
| 104 | preposition get_preposition() const; | ||
| 105 | void set_preposition(preposition _preposition); | ||
| 213 | 106 | ||
| 214 | token* copy() const | ||
| 215 | { | ||
| 216 | return new utterance_token(*this); | ||
| 217 | } | ||
| 218 | }; | ||
| 219 | |||
| 220 | class fillin_token : public token { | ||
| 221 | private: | ||
| 222 | // Fillin | 107 | // Fillin |
| 223 | std::string m_theme; | 108 | token(fillin_type _ft); |
| 224 | fillin_type m_fillin_type; | 109 | token& operator=(fillin_type _ft); |
| 225 | 110 | fillin_type get_fillin_type() const; | |
| 226 | public: | 111 | void set_fillin_type(fillin_type _ft); |
| 227 | fillin_token(fillin_type ft) : token(token::type::fillin), m_fillin_type(ft) | ||
| 228 | { | ||
| 229 | |||
| 230 | } | ||
| 231 | |||
| 232 | /* void synrestrs(std::initializer_list<synrestr> ins) | ||
| 233 | { | ||
| 234 | m_synrestrs = std::set<synrestr>(ins); | ||
| 235 | } | ||
| 236 | |||
| 237 | std::set<synrestr>& synrestrs() | ||
| 238 | { | ||
| 239 | return m_synrestrs; | ||
| 240 | } | ||
| 241 | |||
| 242 | void selrestrs(std::initializer_list<selrestr> ins) | ||
| 243 | { | ||
| 244 | m_selrestrs = std::set<selrestr>(ins); | ||
| 245 | } | ||
| 246 | |||
| 247 | std::set<selrestr>& selrestrs() | ||
| 248 | { | ||
| 249 | return m_selrestrs; | ||
| 250 | }*/ | ||
| 251 | |||
| 252 | fillin_token theme(std::string theme) | ||
| 253 | { | ||
| 254 | m_theme = theme; | ||
| 255 | |||
| 256 | return *this; | ||
| 257 | } | ||
| 258 | 112 | ||
| 259 | std::string& theme() | 113 | // Utterance |
| 260 | { | 114 | typedef std::list<token>::iterator iterator; |
| 261 | return m_theme; | 115 | |
| 262 | } | 116 | token(); |
| 263 | 117 | token(std::initializer_list<token> _init); | |
| 264 | fillin_type get_fillin_type() const | 118 | iterator begin(); |
| 265 | { | 119 | iterator end(); |
| 266 | return m_fillin_type; | 120 | token& operator<<(token _tkn); |
| 267 | } | 121 | void push_back(token _tkn); |
| 268 | 122 | void insert(iterator before, token _tkn); | |
| 269 | bool complete() const | 123 | void replace(iterator torepl, token _tkn); |
| 270 | { | 124 | void erase(iterator toer); |
| 271 | return false; | ||
| 272 | } | ||
| 273 | |||
| 274 | std::string compile() const | ||
| 275 | { | ||
| 276 | return ""; | ||
| 277 | } | ||
| 278 | 125 | ||
| 279 | token* copy() const | ||
| 280 | { | ||
| 281 | return new fillin_token(*this); | ||
| 282 | } | ||
| 283 | }; | ||
| 284 | |||
| 285 | class string_token : public token { | ||
| 286 | private: | ||
| 287 | // String | 126 | // String |
| 288 | std::string str; | 127 | token(std::string _str); |
| 289 | 128 | token& operator=(std::string _str); | |
| 290 | public: | 129 | std::string get_string() const; |
| 291 | string_token(std::string str) : token(token::type::string), str(str) | 130 | void set_string(std::string _str); |
| 292 | { | ||
| 293 | |||
| 294 | } | ||
| 295 | |||
| 296 | bool complete() const | ||
| 297 | { | ||
| 298 | return true; | ||
| 299 | } | ||
| 300 | 131 | ||
| 301 | std::string compile() const | 132 | private: |
| 302 | { | 133 | type _type; |
| 303 | return str; | 134 | int _extra = 0; |
| 304 | } | 135 | union { |
| 305 | 136 | struct { | |
| 306 | token* copy() const | 137 | verb _verb; |
| 307 | { | 138 | verb_inflection _infl; |
| 308 | return new string_token(*this); | 139 | } _verb; |
| 309 | } | 140 | struct { |
| 141 | noun _noun; | ||
| 142 | noun_inflection _infl; | ||
| 143 | } _noun; | ||
| 144 | struct { | ||
| 145 | adjective _adjective; | ||
| 146 | adjective_inflection _infl; | ||
| 147 | } _adjective; | ||
| 148 | struct { | ||
| 149 | adverb _adverb; | ||
| 150 | adverb_inflection _infl; | ||
| 151 | } _adverb; | ||
| 152 | struct { | ||
| 153 | preposition _preposition; | ||
| 154 | } _preposition; | ||
| 155 | struct { | ||
| 156 | fillin_type _type; | ||
| 157 | } _fillin; | ||
| 158 | struct { | ||
| 159 | std::string _str; | ||
| 160 | } _string; | ||
| 161 | struct { | ||
| 162 | std::list<token> _utterance; | ||
| 163 | } _utterance; | ||
| 164 | }; | ||
| 310 | }; | 165 | }; |
| 311 | 166 | ||
| 312 | }; | 167 | }; |
| 313 | 168 | ||
| 314 | #endif /* end of include guard: TOKEN_H_AD62C505 */ | 169 | #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 @@ | |||
| 1 | #ifndef UTIL_H_15DDCA2D | 1 | #ifndef UTIL_H_15DDCA2D |
| 2 | #define UTIL_H_15DDCA2D | 2 | #define UTIL_H_15DDCA2D |
| 3 | 3 | ||
| 4 | #include <string> | ||
| 5 | #include <iterator> | ||
| 6 | #include <sstream> | ||
| 7 | |||
| 8 | namespace verbly { | 4 | namespace verbly { |
| 9 | 5 | ||
| 10 | template <class InputIterator> | 6 | template <class InputIterator> |
| @@ -32,7 +28,7 @@ namespace verbly { | |||
| 32 | 28 | ||
| 33 | while (!input.empty()) | 29 | while (!input.empty()) |
| 34 | { | 30 | { |
| 35 | int divider = input.find(" "); | 31 | int divider = input.find(delimiter); |
| 36 | if (divider == std::string::npos) | 32 | if (divider == std::string::npos) |
| 37 | { | 33 | { |
| 38 | result.push_back(input); | 34 | result.push_back(input); |
| @@ -41,7 +37,7 @@ namespace verbly { | |||
| 41 | } else { | 37 | } else { |
| 42 | result.push_back(input.substr(0, divider)); | 38 | result.push_back(input.substr(0, divider)); |
| 43 | 39 | ||
| 44 | input = input.substr(divider+1); | 40 | input = input.substr(divider+delimiter.length()); |
| 45 | } | 41 | } |
| 46 | } | 42 | } |
| 47 | 43 | ||
| 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 @@ | |||
| 2 | 2 | ||
| 3 | namespace verbly { | 3 | namespace verbly { |
| 4 | 4 | ||
| 5 | verb::verb() | ||
| 6 | { | ||
| 7 | |||
| 8 | } | ||
| 9 | |||
| 5 | verb::verb(const data& _data, int _id) : word(_data, _id) | 10 | verb::verb(const data& _data, int _id) : word(_data, _id) |
| 6 | { | 11 | { |
| 7 | 12 | ||
| @@ -9,185 +14,51 @@ namespace verbly { | |||
| 9 | 14 | ||
| 10 | std::string verb::base_form() const | 15 | std::string verb::base_form() const |
| 11 | { | 16 | { |
| 17 | assert(_valid == true); | ||
| 18 | |||
| 12 | return _infinitive; | 19 | return _infinitive; |
| 13 | } | 20 | } |
| 14 | 21 | ||
| 15 | std::string verb::infinitive_form() const | 22 | std::string verb::infinitive_form() const |
| 16 | { | 23 | { |
| 24 | assert(_valid == true); | ||
| 25 | |||
| 17 | return _infinitive; | 26 | return _infinitive; |
| 18 | } | 27 | } |
| 19 | 28 | ||
| 20 | std::string verb::past_tense_form() const | 29 | std::string verb::past_tense_form() const |
| 21 | { | 30 | { |
| 31 | assert(_valid == true); | ||
| 32 | |||
| 22 | return _past_tense; | 33 | return _past_tense; |
| 23 | } | 34 | } |
| 24 | 35 | ||
| 25 | std::string verb::past_participle_form() const | 36 | std::string verb::past_participle_form() const |
| 26 | { | 37 | { |
| 38 | assert(_valid == true); | ||
| 39 | |||
| 27 | return _past_participle; | 40 | return _past_participle; |
| 28 | } | 41 | } |
| 29 | 42 | ||
| 30 | std::string verb::ing_form() const | 43 | std::string verb::ing_form() const |
| 31 | { | 44 | { |
| 45 | assert(_valid == true); | ||
| 46 | |||
| 32 | return _ing_form; | 47 | return _ing_form; |
| 33 | } | 48 | } |
| 34 | 49 | ||
| 35 | std::string verb::s_form() const | 50 | std::string verb::s_form() const |
| 36 | { | 51 | { |
| 37 | return _s_form; | 52 | assert(_valid == true); |
| 38 | } | ||
| 39 | |||
| 40 | verb_query::verb_query(const data& _data) : _data(_data) | ||
| 41 | { | ||
| 42 | |||
| 43 | } | ||
| 44 | |||
| 45 | verb_query& verb_query::limit(int _limit) | ||
| 46 | { | ||
| 47 | if ((_limit > 0) || (_limit == unlimited)) | ||
| 48 | { | ||
| 49 | this->_limit = _limit; | ||
| 50 | } | ||
| 51 | |||
| 52 | return *this; | ||
| 53 | } | ||
| 54 | |||
| 55 | verb_query& verb_query::random(bool _random) | ||
| 56 | { | ||
| 57 | this->_random = _random; | ||
| 58 | |||
| 59 | return *this; | ||
| 60 | } | ||
| 61 | |||
| 62 | verb_query& verb_query::except(const verb& _word) | ||
| 63 | { | ||
| 64 | _except.push_back(_word); | ||
| 65 | |||
| 66 | return *this; | ||
| 67 | } | ||
| 68 | |||
| 69 | verb_query& verb_query::rhymes_with(const word& _word) | ||
| 70 | { | ||
| 71 | for (auto rhyme : _word.rhyme_phonemes()) | ||
| 72 | { | ||
| 73 | _rhymes.push_back(rhyme); | ||
| 74 | } | ||
| 75 | |||
| 76 | if (dynamic_cast<const verb*>(&_word) != nullptr) | ||
| 77 | { | ||
| 78 | _except.push_back(dynamic_cast<const verb&>(_word)); | ||
| 79 | } | ||
| 80 | 53 | ||
| 81 | return *this; | 54 | return _s_form; |
| 82 | } | 55 | } |
| 83 | 56 | ||
| 84 | verb_query& verb_query::has_pronunciation(bool _has_prn) | 57 | frame_query verb::frames() const |
| 85 | { | 58 | { |
| 86 | this->_has_prn = _has_prn; | 59 | assert(_valid == true); |
| 87 | 60 | ||
| 88 | return *this; | 61 | return _data->frames().for_verb(*this); |
| 89 | } | 62 | } |
| 90 | |||
| 91 | std::list<verb> verb_query::run() const | ||
| 92 | { | ||
| 93 | std::stringstream construct; | ||
| 94 | construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; | ||
| 95 | std::list<std::string> conditions; | ||
| 96 | |||
| 97 | if (_has_prn) | ||
| 98 | { | ||
| 99 | conditions.push_back("verb_id IN (SELECT verb_id FROM verb_pronunciations)"); | ||
| 100 | } | ||
| 101 | |||
| 102 | if (!_rhymes.empty()) | ||
| 103 | { | ||
| 104 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
| 105 | std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 106 | conditions.push_back(cond); | ||
| 107 | } | ||
| 108 | |||
| 109 | for (auto except : _except) | ||
| 110 | { | ||
| 111 | conditions.push_back("verb_id != @EXCID"); | ||
| 112 | } | ||
| 113 | 63 | ||
| 114 | if (!conditions.empty()) | ||
| 115 | { | ||
| 116 | construct << " WHERE "; | ||
| 117 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
| 118 | } | ||
| 119 | |||
| 120 | if (_random) | ||
| 121 | { | ||
| 122 | construct << " ORDER BY RANDOM()"; | ||
| 123 | } | ||
| 124 | |||
| 125 | if (_limit != unlimited) | ||
| 126 | { | ||
| 127 | construct << " LIMIT " << _limit; | ||
| 128 | } | ||
| 129 | |||
| 130 | sqlite3_stmt* ppstmt; | ||
| 131 | std::string query = construct.str(); | ||
| 132 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 133 | { | ||
| 134 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 135 | } | ||
| 136 | |||
| 137 | if (!_rhymes.empty()) | ||
| 138 | { | ||
| 139 | int i = 0; | ||
| 140 | for (auto rhyme : _rhymes) | ||
| 141 | { | ||
| 142 | std::string rhymer = "%" + rhyme; | ||
| 143 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
| 144 | |||
| 145 | i++; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | for (auto except : _except) | ||
| 150 | { | ||
| 151 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
| 152 | } | ||
| 153 | |||
| 154 | std::list<verb> output; | ||
| 155 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 156 | { | ||
| 157 | verb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
| 158 | tnc._infinitive = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
| 159 | tnc._past_tense = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
| 160 | tnc._past_participle = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
| 161 | tnc._ing_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
| 162 | tnc._s_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 5))); | ||
| 163 | |||
| 164 | output.push_back(tnc); | ||
| 165 | } | ||
| 166 | |||
| 167 | sqlite3_finalize(ppstmt); | ||
| 168 | |||
| 169 | for (auto& verb : output) | ||
| 170 | { | ||
| 171 | query = "SELECT pronunciation FROM verb_pronunciations WHERE verb_id = ?"; | ||
| 172 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 173 | { | ||
| 174 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 175 | } | ||
| 176 | |||
| 177 | sqlite3_bind_int(ppstmt, 1, verb._id); | ||
| 178 | |||
| 179 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 180 | { | ||
| 181 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 182 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
| 183 | |||
| 184 | verb.pronunciations.push_back(phonemes); | ||
| 185 | } | ||
| 186 | |||
| 187 | sqlite3_finalize(ppstmt); | ||
| 188 | } | ||
| 189 | |||
| 190 | return output; | ||
| 191 | } | ||
| 192 | |||
| 193 | }; | 64 | }; |
| 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 @@ | |||
| 3 | 3 | ||
| 4 | namespace verbly { | 4 | namespace verbly { |
| 5 | 5 | ||
| 6 | /*class frame_part { | 6 | class frame_query; |
| 7 | |||
| 8 | }; | ||
| 9 | |||
| 10 | class frame { | ||
| 11 | private: | ||
| 12 | std::list<frame_part> content; | ||
| 13 | std::map<std::string, std::vector<std::list<frame_part>::iterator>> predicates; | ||
| 14 | |||
| 15 | public: | ||
| 16 | frame(std::list<frame_part> content) : content(content) | ||
| 17 | { | ||
| 18 | |||
| 19 | } | ||
| 20 | |||
| 21 | std::unique_ptr<token> make_utterance() const | ||
| 22 | { | ||
| 23 | |||
| 24 | } | ||
| 25 | };*/ | ||
| 26 | 7 | ||
| 27 | class verb : public word { | 8 | class verb : public word { |
| 28 | private: | 9 | private: |
| @@ -35,6 +16,7 @@ namespace verbly { | |||
| 35 | friend class verb_query; | 16 | friend class verb_query; |
| 36 | 17 | ||
| 37 | public: | 18 | public: |
| 19 | verb(); | ||
| 38 | verb(const data& _data, int _id); | 20 | verb(const data& _data, int _id); |
| 39 | 21 | ||
| 40 | std::string base_form() const; | 22 | std::string base_form() const; |
| @@ -43,29 +25,8 @@ namespace verbly { | |||
| 43 | std::string past_participle_form() const; | 25 | std::string past_participle_form() const; |
| 44 | std::string ing_form() const; | 26 | std::string ing_form() const; |
| 45 | std::string s_form() const; | 27 | std::string s_form() const; |
| 46 | }; | ||
| 47 | |||
| 48 | class verb_query { | ||
| 49 | public: | ||
| 50 | verb_query(const data& _data); | ||
| 51 | |||
| 52 | verb_query& limit(int _limit); | ||
| 53 | verb_query& random(bool _random); | ||
| 54 | verb_query& except(const verb& _word); | ||
| 55 | verb_query& rhymes_with(const word& _word); | ||
| 56 | verb_query& has_pronunciation(bool _has_prn); | ||
| 57 | 28 | ||
| 58 | std::list<verb> run() const; | 29 | frame_query frames() const; |
| 59 | |||
| 60 | const static int unlimited = -1; | ||
| 61 | |||
| 62 | private: | ||
| 63 | const data& _data; | ||
| 64 | int _limit = unlimited; | ||
| 65 | bool _random = false; | ||
| 66 | std::list<std::string> _rhymes; | ||
| 67 | std::list<verb> _except; | ||
| 68 | bool _has_prn = false; | ||
| 69 | }; | 30 | }; |
| 70 | 31 | ||
| 71 | }; | 32 | }; |
| 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 @@ | |||
| 1 | #include "verbly.h" | ||
| 2 | |||
| 3 | namespace verbly { | ||
| 4 | |||
| 5 | verb_query::verb_query(const data& _data) : _data(_data) | ||
| 6 | { | ||
| 7 | |||
| 8 | } | ||
| 9 | |||
| 10 | verb_query& verb_query::limit(int _limit) | ||
| 11 | { | ||
| 12 | if ((_limit > 0) || (_limit == unlimited)) | ||
| 13 | { | ||
| 14 | this->_limit = _limit; | ||
| 15 | } | ||
| 16 | |||
| 17 | return *this; | ||
| 18 | } | ||
| 19 | |||
| 20 | verb_query& verb_query::random() | ||
| 21 | { | ||
| 22 | this->_random = true; | ||
| 23 | |||
| 24 | return *this; | ||
| 25 | } | ||
| 26 | |||
| 27 | verb_query& verb_query::except(const verb& _word) | ||
| 28 | { | ||
| 29 | _except.push_back(_word); | ||
| 30 | |||
| 31 | return *this; | ||
| 32 | } | ||
| 33 | |||
| 34 | verb_query& verb_query::rhymes_with(const word& _word) | ||
| 35 | { | ||
| 36 | for (auto rhyme : _word.rhyme_phonemes()) | ||
| 37 | { | ||
| 38 | _rhymes.push_back(rhyme); | ||
| 39 | } | ||
| 40 | |||
| 41 | if (dynamic_cast<const verb*>(&_word) != nullptr) | ||
| 42 | { | ||
| 43 | _except.push_back(dynamic_cast<const verb&>(_word)); | ||
| 44 | } | ||
| 45 | |||
| 46 | return *this; | ||
| 47 | } | ||
| 48 | |||
| 49 | verb_query& verb_query::has_pronunciation() | ||
| 50 | { | ||
| 51 | this->_has_prn = true; | ||
| 52 | |||
| 53 | return *this; | ||
| 54 | } | ||
| 55 | |||
| 56 | verb_query& verb_query::has_frames() | ||
| 57 | { | ||
| 58 | this->_has_frames = true; | ||
| 59 | |||
| 60 | return *this; | ||
| 61 | } | ||
| 62 | |||
| 63 | std::list<verb> verb_query::run() const | ||
| 64 | { | ||
| 65 | std::stringstream construct; | ||
| 66 | construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; | ||
| 67 | std::list<std::string> conditions; | ||
| 68 | |||
| 69 | if (_has_prn) | ||
| 70 | { | ||
| 71 | conditions.push_back("verb_id IN (SELECT verb_id FROM verb_pronunciations)"); | ||
| 72 | } | ||
| 73 | |||
| 74 | if (!_rhymes.empty()) | ||
| 75 | { | ||
| 76 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
| 77 | std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
| 78 | conditions.push_back(cond); | ||
| 79 | } | ||
| 80 | |||
| 81 | for (auto except : _except) | ||
| 82 | { | ||
| 83 | conditions.push_back("verb_id != @EXCID"); | ||
| 84 | } | ||
| 85 | |||
| 86 | if (!_has_frames) | ||
| 87 | { | ||
| 88 | conditions.push_back("verb_id IN (SELECT verb_id FROM verb_groups)"); | ||
| 89 | } | ||
| 90 | |||
| 91 | if (!conditions.empty()) | ||
| 92 | { | ||
| 93 | construct << " WHERE "; | ||
| 94 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
| 95 | } | ||
| 96 | |||
| 97 | if (_random) | ||
| 98 | { | ||
| 99 | construct << " ORDER BY RANDOM()"; | ||
| 100 | } | ||
| 101 | |||
| 102 | if (_limit != unlimited) | ||
| 103 | { | ||
| 104 | construct << " LIMIT " << _limit; | ||
| 105 | } | ||
| 106 | |||
| 107 | sqlite3_stmt* ppstmt; | ||
| 108 | std::string query = construct.str(); | ||
| 109 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 110 | { | ||
| 111 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 112 | } | ||
| 113 | |||
| 114 | if (!_rhymes.empty()) | ||
| 115 | { | ||
| 116 | int i = 0; | ||
| 117 | for (auto rhyme : _rhymes) | ||
| 118 | { | ||
| 119 | std::string rhymer = "%" + rhyme; | ||
| 120 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
| 121 | |||
| 122 | i++; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | for (auto except : _except) | ||
| 127 | { | ||
| 128 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
| 129 | } | ||
| 130 | |||
| 131 | std::list<verb> output; | ||
| 132 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 133 | { | ||
| 134 | verb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
| 135 | tnc._infinitive = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
| 136 | tnc._past_tense = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
| 137 | tnc._past_participle = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
| 138 | tnc._ing_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
| 139 | tnc._s_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 5))); | ||
| 140 | |||
| 141 | output.push_back(tnc); | ||
| 142 | } | ||
| 143 | |||
| 144 | sqlite3_finalize(ppstmt); | ||
| 145 | |||
| 146 | for (auto& verb : output) | ||
| 147 | { | ||
| 148 | query = "SELECT pronunciation FROM verb_pronunciations WHERE verb_id = ?"; | ||
| 149 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 150 | { | ||
| 151 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 152 | } | ||
| 153 | |||
| 154 | sqlite3_bind_int(ppstmt, 1, verb._id); | ||
| 155 | |||
| 156 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 157 | { | ||
| 158 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
| 159 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
| 160 | |||
| 161 | verb.pronunciations.push_back(phonemes); | ||
| 162 | } | ||
| 163 | |||
| 164 | sqlite3_finalize(ppstmt); | ||
| 165 | } | ||
| 166 | |||
| 167 | return output; | ||
| 168 | } | ||
| 169 | |||
| 170 | }; | ||
| 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 @@ | |||
| 1 | #ifndef VERB_QUERY_H_34E5A679 | ||
| 2 | #define VERB_QUERY_H_34E5A679 | ||
| 3 | |||
| 4 | namespace verbly { | ||
| 5 | |||
| 6 | class verb_query { | ||
| 7 | public: | ||
| 8 | verb_query(const data& _data); | ||
| 9 | |||
| 10 | verb_query& limit(int _limit); | ||
| 11 | verb_query& random(); | ||
| 12 | verb_query& except(const verb& _word); | ||
| 13 | verb_query& rhymes_with(const word& _word); | ||
| 14 | verb_query& has_pronunciation(); | ||
| 15 | |||
| 16 | verb_query& has_frames(); | ||
| 17 | |||
| 18 | std::list<verb> run() const; | ||
| 19 | |||
| 20 | const static int unlimited = -1; | ||
| 21 | |||
| 22 | private: | ||
| 23 | const data& _data; | ||
| 24 | int _limit = unlimited; | ||
| 25 | bool _random = false; | ||
| 26 | std::list<std::string> _rhymes; | ||
| 27 | std::list<verb> _except; | ||
| 28 | bool _has_prn = false; | ||
| 29 | bool _has_frames = false; | ||
| 30 | }; | ||
| 31 | |||
| 32 | }; | ||
| 33 | |||
| 34 | #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 @@ | |||
| 1 | #ifndef VERBLY_H_5B39CE50 | 1 | #ifndef VERBLY_H_5B39CE50 |
| 2 | #define VERBLY_H_5B39CE50 | 2 | #define VERBLY_H_5B39CE50 |
| 3 | 3 | ||
| 4 | #include "c++14.h" | 4 | #include <string> |
| 5 | #include <list> | ||
| 6 | #include <sstream> | ||
| 7 | #include <algorithm> | ||
| 8 | #include <cassert> | ||
| 9 | #include <set> | ||
| 10 | #include <stdexcept> | ||
| 11 | #include <vector> | ||
| 12 | #include <map> | ||
| 13 | #include <iterator> | ||
| 14 | #include <sstream> | ||
| 15 | #include <functional> | ||
| 16 | #include <iostream> | ||
| 17 | #include <new> | ||
| 18 | |||
| 5 | #include "util.h" | 19 | #include "util.h" |
| 6 | #include "token.h" | ||
| 7 | #include "data.h" | 20 | #include "data.h" |
| 8 | #include "word.h" | 21 | #include "word.h" |
| 9 | #include "verb.h" | 22 | #include "verb.h" |
| 10 | #include "adverb.h" | 23 | #include "adverb.h" |
| 11 | #include "adjective.h" | 24 | #include "adjective.h" |
| 12 | #include "noun.h" | 25 | #include "noun.h" |
| 26 | #include "frame.h" | ||
| 27 | #include "preposition.h" | ||
| 28 | #include "token.h" | ||
| 29 | #include "noun_query.h" | ||
| 30 | #include "adverb_query.h" | ||
| 31 | #include "adjective_query.h" | ||
| 32 | #include "verb_query.h" | ||
| 33 | #include "frame_query.h" | ||
| 13 | 34 | ||
| 14 | #endif /* end of include guard: VERBLY_H_5B39CE50 */ | 35 | #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 @@ | |||
| 3 | 3 | ||
| 4 | namespace verbly { | 4 | namespace verbly { |
| 5 | 5 | ||
| 6 | word::word(const data& _data, int _id) : _data(_data), _id(_id) | 6 | word::word() |
| 7 | { | ||
| 8 | |||
| 9 | } | ||
| 10 | |||
| 11 | word::word(const data& _data, int _id) : _data(&_data), _id(_id), _valid(true) | ||
| 7 | { | 12 | { |
| 8 | 13 | ||
| 9 | } | 14 | } |
| 10 | 15 | ||
| 11 | std::list<std::string> word::rhyme_phonemes() const | 16 | std::list<std::string> word::rhyme_phonemes() const |
| 12 | { | 17 | { |
| 18 | assert(_valid == true); | ||
| 19 | |||
| 13 | std::list<std::string> result; | 20 | std::list<std::string> result; |
| 14 | 21 | ||
| 15 | for (auto pronunciation : pronunciations) | 22 | for (auto pronunciation : pronunciations) |
| @@ -32,6 +39,8 @@ namespace verbly { | |||
| 32 | 39 | ||
| 33 | bool word::starts_with_vowel_sound() const | 40 | bool word::starts_with_vowel_sound() const |
| 34 | { | 41 | { |
| 42 | assert(_valid == true); | ||
| 43 | |||
| 35 | if (pronunciations.size() > 0) | 44 | if (pronunciations.size() > 0) |
| 36 | { | 45 | { |
| 37 | return std::any_of(std::begin(pronunciations), std::end(pronunciations), [] (std::list<std::string> phonemes) { | 46 | return std::any_of(std::begin(pronunciations), std::end(pronunciations), [] (std::list<std::string> 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 @@ | |||
| 3 | 3 | ||
| 4 | namespace verbly { | 4 | namespace verbly { |
| 5 | 5 | ||
| 6 | class adjective_query; | ||
| 7 | class verb_query; | ||
| 8 | class adverb_query; | ||
| 9 | |||
| 10 | template <class T> | ||
| 11 | class query; | ||
| 12 | |||
| 13 | class word { | 6 | class word { |
| 14 | protected: | 7 | protected: |
| 15 | const data& _data; | 8 | const data* _data; |
| 16 | int _id; | 9 | int _id; |
| 10 | bool _valid = false; | ||
| 17 | 11 | ||
| 18 | std::list<std::list<std::string>> pronunciations; | 12 | std::list<std::list<std::string>> pronunciations; |
| 19 | 13 | ||
| 14 | word(); | ||
| 20 | word(const data& _data, int _id); | 15 | word(const data& _data, int _id); |
| 21 | 16 | ||
| 22 | friend class adjective_query; | 17 | friend class adjective_query; |
| 23 | friend class verb_query; | 18 | friend class verb_query; |
| 24 | friend class noun_query; | 19 | friend class noun_query; |
| 25 | friend class adverb_query; | 20 | friend class adverb_query; |
| 21 | friend class frame_query; | ||
| 22 | friend class preposition_query; | ||
| 26 | 23 | ||
| 27 | public: | 24 | public: |
| 28 | virtual std::string base_form() const = 0; | 25 | virtual std::string base_form() const = 0; |
| diff --git a/vendor/json b/vendor/json new file mode 160000 | |||
| Subproject 2b137110095c2b2046cde5af4ac8892b8a3f380 | |||
