summary refs log tree commit diff stats
path: root/lib/adjective.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/adjective.cpp')
-rw-r--r--lib/adjective.cpp690
1 files changed, 690 insertions, 0 deletions
diff --git a/lib/adjective.cpp b/lib/adjective.cpp new file mode 100644 index 0000000..b2b53e4 --- /dev/null +++ b/lib/adjective.cpp
@@ -0,0 +1,690 @@
1#include "verbly.h"
2
3namespace verbly {
4
5 adjective::adjective(const data& _data, int _id) : word(_data, _id)
6 {
7
8 }
9
10 std::string adjective::base_form() const
11 {
12 return _base_form;
13 }
14
15 std::string adjective::comparative_form() const
16 {
17 return _comparative_form;
18 }
19
20 std::string adjective::superlative_form() const
21 {
22 return _superlative_form;
23 }
24
25 adjective::positioning adjective::position() const
26 {
27 return _position;
28 }
29
30 bool adjective::has_comparative_form() const
31 {
32 return !_comparative_form.empty();
33 }
34
35 bool adjective::has_superlative_form() const
36 {
37 return !_superlative_form.empty();
38 }
39
40 bool adjective::has_position() const
41 {
42 return _position != adjective::positioning::undefined;
43 }
44
45 adjective_query adjective::antonyms() const
46 {
47 return _data.adjectives().antonym_of(*this);
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
226 return *this;
227 }
228
229 adjective_query& adjective_query::not_specification_of(const adjective& _adj)
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 {
245 _pertainym_of.push_back(_noun);
246
247 return *this;
248 }
249
250 adjective_query& adjective_query::is_mannernymic(bool _is_mannernymic)
251 {
252 this->_is_mannernymic = _is_mannernymic;
253
254 return *this;
255 }
256
257 adjective_query& adjective_query::anti_mannernym_of(const adverb& _adv)
258 {
259 _anti_mannernym_of.push_back(_adv);
260
261 return *this;
262 }
263
264 adjective_query& adjective_query::derived_from(const word& _w)
265 {
266 if (dynamic_cast<const adjective*>(&_w) != nullptr)
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
277 return *this;
278 }
279
280 adjective_query& adjective_query::not_derived_from(const word& _w)
281 {
282 if (dynamic_cast<const adjective*>(&_w) != nullptr)
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
293 return *this;
294 }
295
296 std::list<adjective> adjective_query::run() const
297 {
298 std::stringstream construct;
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
377 if (_is_synonymic)
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 }
689
690};