summary refs log tree commit diff stats
path: root/lib
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 /lib
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.
Diffstat (limited to 'lib')
-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
31 files changed, 5241 insertions, 2827 deletions
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;