summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2016-03-24 23:16:07 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2016-03-24 23:16:07 -0400
commiteef5de613c75661e5d94baa086f6f2ddc26c7ed0 (patch)
tree180230f6a245c5bca94d894273f5d2b93ded3f04
parentd5ee4e39e5b5b3b8daa85cd972802195ad35e965 (diff)
downloadverbly-eef5de613c75661e5d94baa086f6f2ddc26c7ed0.tar.gz
verbly-eef5de613c75661e5d94baa086f6f2ddc26c7ed0.tar.bz2
verbly-eef5de613c75661e5d94baa086f6f2ddc26c7ed0.zip
Added verb frames
In addition:
- Added prepositions.
- Rewrote a lot of the query interface. It now, for a lot of relationships, supports nested AND, OR, and NOT logic.
- Rewrote the token class. It is now a union-like class instead of being polymorphic, which means smart pointers are no longer necessary.
- Querying with regards to word derivation has been temporarily removed.
- Sentinel values are now supported for all word types.
- The VerbNet data retrieved from http://verbs.colorado.edu/~mpalmer/projects/verbnet/downloads.html was found to not be perfectly satisfactory in some regards, especially regarding adjective phrases. A patch file is now included in the repository describing the changes made to the VerbNet v3.2 download for the canonical verbly datafile.
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt3
-rw-r--r--LICENSE48
-rw-r--r--generator/CMakeLists.txt2
-rw-r--r--generator/generator.cpp545
-rw-r--r--generator/prepositions.txt49
-rw-r--r--generator/schema.sql16
-rw-r--r--generator/vn.diff482
-rw-r--r--lib/adjective.cpp655
-rw-r--r--lib/adjective.h94
-rw-r--r--lib/adjective_query.cpp819
-rw-r--r--lib/adjective_query.h91
-rw-r--r--lib/adverb.cpp443
-rw-r--r--lib/adverb.h62
-rw-r--r--lib/adverb_query.cpp514
-rw-r--r--lib/adverb_query.h65
-rw-r--r--lib/c++14.h35
-rw-r--r--lib/data.cpp12
-rw-r--r--lib/data.h299
-rw-r--r--lib/frame.cpp320
-rw-r--r--lib/frame.h118
-rw-r--r--lib/frame_query.cpp142
-rw-r--r--lib/frame_query.h21
-rw-r--r--lib/noun.cpp1010
-rw-r--r--lib/noun.h150
-rw-r--r--lib/noun_query.cpp1453
-rw-r--r--lib/noun_query.h139
-rw-r--r--lib/preposition.cpp83
-rw-r--r--lib/preposition.h38
-rw-r--r--lib/token.cpp617
-rw-r--r--lib/token.h413
-rw-r--r--lib/util.h8
-rw-r--r--lib/verb.cpp169
-rw-r--r--lib/verb.h45
-rw-r--r--lib/verb_query.cpp170
-rw-r--r--lib/verb_query.h34
-rw-r--r--lib/verbly.h25
-rw-r--r--lib/word.cpp11
-rw-r--r--lib/word.h13
m---------vendor/json0
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)
4find_package(PkgConfig) 4find_package(PkgConfig)
5pkg_check_modules(sqlite3 sqlite3 REQUIRED) 5pkg_check_modules(sqlite3 sqlite3 REQUIRED)
6 6
7add_library(verbly lib/data.cpp lib/adjective.cpp lib/noun.cpp lib/verb.cpp lib/adverb.cpp lib/token.cpp lib/word.cpp) 7include_directories(vendor/json/src)
8add_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)
8set_property(TARGET verbly PROPERTY CXX_STANDARD 11) 9set_property(TARGET verbly PROPERTY CXX_STANDARD 11)
9set_property(TARGET verbly PROPERTY CXX_STANDARD_REQUIRED ON) 10set_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
72redistribute this material we request that you acknowledge its 72redistribute this material we request that you acknowledge its
73origin in your descriptions, as per the license information included 73origin in your descriptions, as per the license information included
74in the dictionary file (a Simplified BSD lincense). 74in the dictionary file (a Simplified BSD lincense).
75
76VerbNet v3.2
77============
78 VerbNet 3.0 License (also applies to VerbNet 3.X versions)
79
80This software and database is being provided to you, the LICENSEE, by
81the University of Colorado under the following license. By obtaining, using
82and/or copying this software and database, you agree that you have
83read, understood, and will comply with these terms and conditions.:
84
85Permission to use, copy, modify and distribute this software and
86database and its documentation for any purpose and without fee or
87royalty is hereby granted, provided that you agree to comply with
88the following copyright notice and statements, including the disclaimer,
89and that the same appear on ALL copies of the software, database and
90documentation, including modifications that you make for internal
91use or for distribution.
92
93VerbNet 3.0 (or 3.X) Copyright 2009 by University of Colorado. All rights reserved.
94
95THIS SOFTWARE AND DATABASE IS PROVIDED "AS IS" AND THE UNIVERSITY
96OF COLORADO MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
97IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, UNIVERSITY
98OF COLORADO MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANT-
99ABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE
100OF THE LICENSED SOFTWARE, DATABASE OR DOCUMENTATION WILL NOT
101INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR
102OTHER RIGHTS.
103
104The name of University of Colorado or CU may not be used in
105advertising or publicity pertaining to distribution of the software
106and/or database. Title to copyright in this software, database and
107any associated documentation shall at all times remain with
108University of Colorado and LICENSEE agrees to preserve same.
109
110Please reference the following document(s) in any description of
111applications based on VerbNet 3.0 or 3.X:
112
113Karin Kipper, Anna Korhonen, Neville Ryant, Martha Palmer,
114A Large-scale Classification of English Verbs,
115Language Resources and Evaluation Journal, 42(1), pp. 21-40,
116Springer Netherland, 2008.
117
118and/or
119
120Karin Kipper Schuler, Anna Korhonen, Susan W. Brown, VerbNet overview,
121extensions, mappings and apps, Tutorial, NAACL-HLT 2009, Boulder,
122Colorado. \ 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)
5pkg_check_modules(sqlite3 sqlite3 REQUIRED) 5pkg_check_modules(sqlite3 sqlite3 REQUIRED)
6find_package(libxml2 REQUIRED) 6find_package(libxml2 REQUIRED)
7 7
8include_directories(${sqlite3_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) 8include_directories(${sqlite3_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR} ../vendor/json/src)
9add_executable(generator generator.cpp) 9add_executable(generator generator.cpp)
10set_property(TARGET generator PROPERTY CXX_STANDARD 11) 10set_property(TARGET generator PROPERTY CXX_STANDARD 11)
11set_property(TARGET generator PROPERTY CXX_STANDARD_REQUIRED ON) 11set_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
16struct verb { 18using json = nlohmann::json;
19
20struct 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
24struct adjective { 29struct 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
30struct noun { 35struct noun_t {
31 std::string singular; 36 std::string singular;
32 std::string plural; 37 std::string plural;
33}; 38};
34 39
35struct group { 40struct 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
53struct 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
71struct 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
40std::map<std::string, group> groups; 79std::map<std::string, group_t> groups;
41std::map<std::string, verb> verbs; 80std::map<std::string, verb_t> verbs;
42std::map<std::string, adjective> adjectives; 81std::map<std::string, adjective_t> adjectives;
43std::map<std::string, noun> nouns; 82std::map<std::string, noun_t> nouns;
44std::map<int, std::map<int, int>> wn; 83std::map<int, std::map<int, int>> wn;
45std::map<std::string, std::set<std::string>> pronunciations; 84std::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
62void db_error(sqlite3* ppdb, std::string) 101void 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/* 109json export_selrestrs(selrestr_t r)
70void 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
137selrestr_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
191group_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
114int main(int argc, char** argv) 377int 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 @@
1from: src, path, spatial, loc
2out: src, path, spatial
3out of: src, path, spatial, loc
4off: src, path, spatial, loc
5off of: src, path, spatial
6into: dest_conf, dest, path, spatial
7onto: dest_conf, dest, path, spatial
8for: dest_dir, dest, path, spatial
9at: dest_dir, dest, path, spatial, loc
10to: dest_dir, dest, path, spatial
11towards: dest_dir, dest, path, spatial
12along: dir, path, spatial, loc
13across: dir, path, spatial
14around: dir, path, spatial, loc
15down: dir, path, spatial
16over: dir, path, spatial, loc
17past: dir, path, spatial
18round: dir, path, spatial, loc
19through: dir, path, spatial
20towards: dir, path, spatial
21up: dir, path, spatial
22about: loc, spatial
23above: loc, spatial
24against: loc, spatial
25alongside: loc, spatial
26amid: loc, spatial
27among: loc, spatial
28amongst: loc, spatial
29astride: loc, spatial
30athwart: loc, spatial
31before: loc, spatial
32behind: loc, spatial
33beside: loc, spatial
34between: loc, spatial
35beyond: loc, spatial
36by: loc, spatial
37in: loc, spatial
38in front of: loc, spatial
39inside: loc, spatial
40near: loc, spatial
41next to: loc, spatial
42on: loc, spatial
43opposite: loc, spatial
44outside: loc, spatial
45throughout: loc, spatial
46under: loc, spatial
47underneath: loc, spatial
48upon: loc, spatial
49within: 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` (
11DROP TABLE IF EXISTS `groups`; 11DROP TABLE IF EXISTS `groups`;
12CREATE TABLE `groups` ( 12CREATE 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
18DROP TABLE IF EXISTS `frames`; 17DROP 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
254DROP TABLE IF EXISTS `prepositions`;
255CREATE TABLE `prepositions` (
256 `preposition_id` INTEGER PRIMARY KEY,
257 `form` VARCHAR(32) NOT NULL
258);
259
260DROP TABLE IF EXISTS `preposition_groups`;
261CREATE 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 @@
1diff /Users/hatkirby/Downloads/new_vn 2/admit-65.xml datadir/vn/admit-65.xml
2104c104
3< <SELRESTRS logic="or">
4---
5> <SELRESTRS>
6diff /Users/hatkirby/Downloads/new_vn 2/amuse-31.1.xml datadir/vn/amuse-31.1.xml
7270a271,273
8> <THEMROLE type="Cause">
9> <SELRESTRS/>
10> </THEMROLE>
11368c371,373
12< <LEX value="'s"/>
13---
14> <NP value="Cause">
15> <SYNRESTRS/>
16> </NP>
17404c409,411
18< <SYNRESTRS/>
19---
20> <SYNRESTRS>
21> <SYNRESTR Value="+" type="adjp"/>
22> </SYNRESTRS>
23diff /Users/hatkirby/Downloads/new_vn 2/animal_sounds-38.xml datadir/vn/animal_sounds-38.xml
24186a187,191
25> <PREP>
26> <SELRESTRS>
27> <SELRESTR Value="+" type="loc" />
28> </SELRESTRS>
29> </PREP>
30diff /Users/hatkirby/Downloads/new_vn 2/assessment-34.1.xml datadir/vn/assessment-34.1.xml
31103d102
32< <LEX value="'s"/>
33diff /Users/hatkirby/Downloads/new_vn 2/battle-36.4.xml datadir/vn/battle-36.4.xml
3496c96
35< <SYNRESTR Value="+" type="what_extract"/>
36---
37> <SYNRESTR Value="+" type="wh_comp"/>
38diff /Users/hatkirby/Downloads/new_vn 2/become-109.1.xml datadir/vn/become-109.1.xml
3934c34,36
40< <SYNRESTRS/>
41---
42> <SYNRESTRS>
43> <SYNRESTR Value="+" type="adjp"/>
44> </SYNRESTRS>
45diff /Users/hatkirby/Downloads/new_vn 2/beg-58.2.xml datadir/vn/beg-58.2.xml
4641c41
47< <SYNRESTR Value="-" type="for_comp"/>
48---
49> <SYNRESTR Value="+" type="for_comp"/>
50diff /Users/hatkirby/Downloads/new_vn 2/bend-45.2.xml datadir/vn/bend-45.2.xml
5147c47,49
52< <SELRESTRS/>
53---
54> <SELRESTRS>
55> <SELRESTR Value="+" type="state"/>
56> </SELRESTRS>
57230c232,234
58< <SYNRESTRS/>
59---
60> <SYNRESTRS>
61> <SYNRESTR Value="+" type="adjp"/>
62> </SYNRESTRS>
63280,282c284
64< <SELRESTRS>
65< <SELRESTR Value="+" type="state"/>
66< </SELRESTRS>
67---
68> <SELRESTRS/>
69332,334c334
70< <SELRESTRS>
71< <SELRESTR Value="+" type="state"/>
72< </SELRESTRS>
73---
74> <SELRESTRS/>
75diff /Users/hatkirby/Downloads/new_vn 2/break-45.1.xml datadir/vn/break-45.1.xml
76255c255,257
77< <SYNRESTRS/>
78---
79> <SYNRESTRS>
80> <SYNRESTR Value="+" type="adjp"/>
81> </SYNRESTRS>
82307c309,311
83< <SYNRESTRS/>
84---
85> <SYNRESTRS>
86> <SYNRESTR Value="+" type="adjp"/>
87> </SYNRESTRS>
88diff /Users/hatkirby/Downloads/new_vn 2/characterize-29.2.xml datadir/vn/characterize-29.2.xml
89107c107
90< <LEX value="as"/>
91---
92> <LEX value="to be"/>
93109,111c109,111
94< <SYNRESTRS>
95< <SYNRESTR Value="+" type="small_clause"/>
96< </SYNRESTRS>
97---
98> <SYNRESTRS>
99> <SYNRESTR Value="+" type="adjp"/>
100> </SYNRESTRS>
101386a387,391
102> <NP value="Attribute">
103> <SYNRESTRS>
104> <SYNRESTR Value="+" type="adjp"/>
105> </SYNRESTRS>
106> </NP>
107diff /Users/hatkirby/Downloads/new_vn 2/coloring-24.xml datadir/vn/coloring-24.xml
10889c89,91
109< <SYNRESTRS/>
110---
111> <SYNRESTRS>
112> <SYNRESTR Value="+" type="adjp"/>
113> </SYNRESTRS>
114diff /Users/hatkirby/Downloads/new_vn 2/confess-37.10.xml datadir/vn/confess-37.10.xml
115110a111,115
116> <NP value="Attribute">
117> <SYNRESTRS>
118> <SYNRESTR Value="+" type="adjp"/>
119> </SYNRESTRS>
120> </NP>
121diff /Users/hatkirby/Downloads/new_vn 2/consider-29.9.xml datadir/vn/consider-29.9.xml
122191,193c191,193
123< <SYNRESTRS>
124< <SYNRESTR Value="-" type="sentential"/>
125< </SYNRESTRS>
126---
127> <SYNRESTRS>
128> <SYNRESTR Value="+" type="adjp"/>
129> </SYNRESTRS>
130334,336c334,336
131< <SYNRESTRS>
132< <SYNRESTR Value="-" type="sentential"/>
133< </SYNRESTRS>
134---
135> <SYNRESTRS>
136> <SYNRESTR Value="+" type="adjp"/>
137> </SYNRESTRS>
138468,470c468,470
139< <SYNRESTRS>
140< <SYNRESTR Value="-" type="sentential"/>
141< </SYNRESTRS>
142---
143> <SYNRESTRS>
144> <SYNRESTR Value="+" type="adjp"/>
145> </SYNRESTRS>
146554,556c554,556
147< <SYNRESTRS>
148< <SYNRESTR Value="-" type="sentential"/>
149< </SYNRESTRS>
150---
151> <SYNRESTRS>
152> <SYNRESTR Value="+" type="adjp"/>
153> </SYNRESTRS>
154diff /Users/hatkirby/Downloads/new_vn 2/cut-21.1.xml datadir/vn/cut-21.1.xml
155316c316,318
156< <SYNRESTRS/>
157---
158> <SYNRESTRS>
159> <SYNRESTR Value="+" type="adjp"/>
160> </SYNRESTRS>
161368c370,372
162< <SYNRESTRS/>
163---
164> <SYNRESTRS>
165> <SYNRESTR Value="+" type="adjp"/>
166> </SYNRESTRS>
167560c564,566
168< <SYNRESTRS/>
169---
170> <SYNRESTRS>
171> <SYNRESTR Value="+" type="adjp"/>
172> </SYNRESTRS>
173diff /Users/hatkirby/Downloads/new_vn 2/declare-29.4.xml datadir/vn/declare-29.4.xml
17433,35c33,35
175< <SYNRESTRS>
176< <SYNRESTR Value="-" type="sentential"/>
177< </SYNRESTRS>
178---
179> <SYNRESTRS>
180> <SYNRESTR Value="+" type="adjp"/>
181> </SYNRESTRS>
182122,124c122,124
183< <SYNRESTRS>
184< <SYNRESTR Value="-" type="sentential"/>
185< </SYNRESTRS>
186---
187> <SYNRESTRS>
188> <SYNRESTR Value="+" type="adjp"/>
189> </SYNRESTRS>
190244,246c244,246
191< <SYNRESTRS>
192< <SYNRESTR Value="-" type="sentential"/>
193< </SYNRESTRS>
194---
195> <SYNRESTRS>
196> <SYNRESTR Value="+" type="adjp"/>
197> </SYNRESTRS>
198diff /Users/hatkirby/Downloads/new_vn 2/estimate-34.2.xml datadir/vn/estimate-34.2.xml
199123a124
200> <LEX value="to be"/>
201125,127c126,128
202< <SYNRESTRS>
203< <SYNRESTR Value="+" type="to_be"/>
204< </SYNRESTRS>
205---
206> <SYNRESTRS>
207> <SYNRESTR Value="+" type="adjp"/>
208> </SYNRESTRS>
209diff /Users/hatkirby/Downloads/new_vn 2/get-13.5.1.xml datadir/vn/get-13.5.1.xml
21055,56c55
211< <SELRESTR Value="-" type="location"/>
212< <SELRESTR Value="-" type="region"/>
213---
214> <SELRESTR Value="+" type="currency"/>
215diff /Users/hatkirby/Downloads/new_vn 2/hit-18.1.xml datadir/vn/hit-18.1.xml
216234c234,236
217< <SYNRESTRS/>
218---
219> <SYNRESTRS>
220> <SYNRESTR Value="+" type="adjp"/>
221> </SYNRESTRS>
222294c296,298
223< <SYNRESTRS/>
224---
225> <SYNRESTRS>
226> <SYNRESTR Value="+" type="adjp"/>
227> </SYNRESTRS>
228619c623,625
229< <SYNRESTRS/>
230---
231> <SYNRESTRS>
232> <SYNRESTR Value="+" type="adjp"/>
233> </SYNRESTRS>
234diff /Users/hatkirby/Downloads/new_vn 2/instr_communication-37.4.xml datadir/vn/instr_communication-37.4.xml
235195c195,197
236< <SYNRESTRS/>
237---
238> <SYNRESTRS>
239> <SYNRESTR Value="+" type="quotation"/>
240> </SYNRESTRS>
241233c235,237
242< <SYNRESTRS/>
243---
244> <SYNRESTRS>
245> <SYNRESTR Value="+" type="quotation"/>
246> </SYNRESTRS>
247diff /Users/hatkirby/Downloads/new_vn 2/judgment-33.xml datadir/vn/judgment-33.xml
248187a188,190
249> <NP value="Attribute">
250> <SYNRESTRS/>
251> </NP>
252243a247
253> <LEX value="to be"/>
254245,247c249
255< <SYNRESTRS>
256< <SYNRESTR Value="+" type="small_clause"/>
257< </SYNRESTRS>
258---
259> <SYNRESTRS/>
260diff /Users/hatkirby/Downloads/new_vn 2/manner_speaking-37.3.xml datadir/vn/manner_speaking-37.3.xml
261264c264,266
262< <SYNRESTRS/>
263---
264> <SYNRESTRS>
265> <SYNRESTR Value="+" type="quotation"/>
266> </SYNRESTRS>
267603c605,607
268< <SYNRESTRS/>
269---
270> <SYNRESTRS>
271> <SYNRESTR Value="+" type="quotation"/>
272> </SYNRESTRS>
273diff /Users/hatkirby/Downloads/new_vn 2/other_cos-45.4.xml datadir/vn/other_cos-45.4.xml
274534c534,536
275< <SYNRESTRS/>
276---
277> <SYNRESTRS>
278> <SYNRESTR Value="+" type="adjp"/>
279> </SYNRESTRS>
280diff /Users/hatkirby/Downloads/new_vn 2/pocket-9.10.xml datadir/vn/pocket-9.10.xml
281256c256,258
282< <SYNRESTRS/>
283---
284> <SYNRESTRS>
285> <SYNRESTR Value="+" type="adv-loc"/>
286> </SYNRESTRS>
287diff /Users/hatkirby/Downloads/new_vn 2/poison-42.2.xml datadir/vn/poison-42.2.xml
28893c93,95
289< <SYNRESTRS/>
290---
291> <SYNRESTRS>
292> <SYNRESTR Value="+" type="adjp"/>
293> </SYNRESTRS>
294diff /Users/hatkirby/Downloads/new_vn 2/pour-9.5.xml datadir/vn/pour-9.5.xml
29559,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"/>
304157,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>
315diff /Users/hatkirby/Downloads/new_vn 2/push-12.xml datadir/vn/push-12.xml
31690c90,92
317< <SYNRESTRS/>
318---
319> <SYNRESTRS>
320> <SYNRESTR Value="+" type="adjp"/>
321> </SYNRESTRS>
322diff /Users/hatkirby/Downloads/new_vn 2/roll-51.3.1.xml datadir/vn/roll-51.3.1.xml
323190c190,192
324< <SYNRESTRS/>
325---
326> <SYNRESTRS>
327> <SYNRESTR Value="+" type="adjp"/>
328> </SYNRESTRS>
329256c258,260
330< <SYNRESTRS/>
331---
332> <SYNRESTRS>
333> <SYNRESTR Value="+" type="adjp"/>
334> </SYNRESTRS>
335diff /Users/hatkirby/Downloads/new_vn 2/see-30.1.xml datadir/vn/see-30.1.xml
33616a17,19
337> <THEMROLE type="Patient">
338> <SELRESTRS/>
339> </THEMROLE>
34093a97,102
341> <PREP value="in">
342> <SELRESTRS/>
343> </PREP>
344> <NP value="Patient">
345> <SYNRESTRS/>
346> </NP>
347231a241,243
348> <NP value="Patient">
349> <SYNRESTRS/>
350> </NP>
351diff /Users/hatkirby/Downloads/new_vn 2/seem-109.xml datadir/vn/seem-109.xml
35230,32c30,32
353< <SYNRESTRS>
354< <SYNRESTR Value="-" type="sentential"/>
355< </SYNRESTRS>
356---
357> <SYNRESTRS>
358> <SYNRESTR Value="+" type="adjp"/>
359> </SYNRESTRS>
360diff /Users/hatkirby/Downloads/new_vn 2/slide-11.2.xml datadir/vn/slide-11.2.xml
36169,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>
372218,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>
383diff /Users/hatkirby/Downloads/new_vn 2/spank-18.3.xml datadir/vn/spank-18.3.xml
38469a70,72
385> <THEMROLE type="Recipient">
386> <SELRESTRS/>
387> </THEMROLE>
388201c204,206
389< <SYNRESTRS/>
390---
391> <SYNRESTRS>
392> <SYNRESTR Value="+" type="adjp"/>
393> </SYNRESTRS>
394529,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>
408diff /Users/hatkirby/Downloads/new_vn 2/swat-18.2.xml datadir/vn/swat-18.2.xml
409264c264,266
410< <SYNRESTRS/>
411---
412> <SYNRESTRS>
413> <SYNRESTR Value="+" type="adjp"/>
414> </SYNRESTRS>
415324c326,328
416< <SYNRESTRS/>
417---
418> <SYNRESTRS>
419> <SYNRESTR Value="+" type="adjp"/>
420> </SYNRESTRS>
421diff /Users/hatkirby/Downloads/new_vn 2/tape-22.4.xml datadir/vn/tape-22.4.xml
422364c364,366
423< <SYNRESTRS/>
424---
425> <SYNRESTRS>
426> <SYNRESTR Value="+" type="adjp"/>
427> </SYNRESTRS>
428diff /Users/hatkirby/Downloads/new_vn 2/vehicle-51.4.1.xml datadir/vn/vehicle-51.4.1.xml
429227c227,229
430< <SYNRESTRS/>
431---
432> <SYNRESTRS>
433> <SYNRESTR Value="+" type="adjp"/>
434> </SYNRESTRS>
435diff /Users/hatkirby/Downloads/new_vn 2/waltz-51.5.xml datadir/vn/waltz-51.5.xml
436181c181,183
437< <SYNRESTRS/>
438---
439> <SYNRESTRS>
440> <SYNRESTR Value="+" type="adjp"/>
441> </SYNRESTRS>
442diff /Users/hatkirby/Downloads/new_vn 2/want-32.1.xml datadir/vn/want-32.1.xml
443142a143
444> <ADV/>
445194a196
446> <ADJ/>
447305a308
448> <LEX value="to be"/>
449307,309c310,312
450< <SYNRESTRS>
451< <SYNRESTR Value="+" type="to_be"/>
452< </SYNRESTRS>
453---
454> <SYNRESTRS>
455> <SYNRESTR Value="+" type="adjp"/>
456> </SYNRESTRS>
457diff /Users/hatkirby/Downloads/new_vn 2/wipe_instr-10.4.2.xml datadir/vn/wipe_instr-10.4.2.xml
458178c178,180
459< <SYNRESTRS/>
460---
461> <SYNRESTRS>
462> <SYNRESTR Value="+" type="adjp"/>
463> </SYNRESTRS>
464diff /Users/hatkirby/Downloads/new_vn 2/wipe_manner-10.4.1.xml datadir/vn/wipe_manner-10.4.1.xml
465198c198,199
466< <SELRESTR Value="-" type="region"/>
467---
468> <SELRESTR Value="+" type="location"/>
469> <SELRESTR Value="-" type="region"/>
470diff /Users/hatkirby/Downloads/new_vn 2/wish-62.xml datadir/vn/wish-62.xml
47191a92
472> <LEX value="to be"/>
47393,95c94,96
474< <SYNRESTRS>
475< <SYNRESTR Value="+" type="to_be"/>
476< </SYNRESTRS>
477---
478> <SYNRESTRS>
479> <SYNRESTR Value="+" type="adjp"/>
480> </SYNRESTRS>
481122a124
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
3namespace verbly { 3namespace 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
3namespace 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
4namespace 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
3namespace verbly { 3namespace 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
3namespace 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
4namespace 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
6namespace 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
7namespace verbly { 6namespace 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
3namespace 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
4namespace 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
4using json = nlohmann::json;
5
6namespace 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
4namespace 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
3namespace verbly { 5namespace 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
3namespace 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
4namespace 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
3namespace 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
4namespace 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
3namespace verbly { 3namespace 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
9namespace verbly { 4namespace 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
8namespace verbly { 4namespace 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
3namespace verbly { 3namespace 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
4namespace verbly { 4namespace 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
3namespace 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
4namespace 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
4namespace verbly { 4namespace 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
4namespace verbly { 4namespace 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