summary refs log tree commit diff stats
path: root/lib/adjective_query.cpp
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2017-01-16 18:02:50 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2017-01-16 18:02:50 -0500
commit6746da6edd7d9d50efe374eabbb79a3cac882d81 (patch)
treeff20917e08b08d36b9541c1371106596e7bec442 /lib/adjective_query.cpp
parent4af7e55733098ca42f75a4ffaca1b0f6bab4dd36 (diff)
downloadverbly-6746da6edd7d9d50efe374eabbb79a3cac882d81.tar.gz
verbly-6746da6edd7d9d50efe374eabbb79a3cac882d81.tar.bz2
verbly-6746da6edd7d9d50efe374eabbb79a3cac882d81.zip
Started structural rewrite
The new object structure was designed to build on the existing WordNet
structure, while also adding in all of the data that we get from other sources.
More information about this can be found on the project wiki.

The generator has already been completely rewritten to generate a
datafile that uses the new structure. In addition, a number of indexes
are created, which does double the size of the datafile, but also allows
for much faster lookups. Finally, the new generator is written modularly
and is a lot more readable than the old one.

The verbly interface to the new object structure has mostly been
completed, but has not been tested fully. There is a completely new
search API which utilizes a lot of operator overloading; documentation
on how to use it should go up at some point.

Token processing and verb frames are currently unimplemented. Source for
these have been left in the repository for now.
Diffstat (limited to 'lib/adjective_query.cpp')
-rw-r--r--lib/adjective_query.cpp1072
1 files changed, 0 insertions, 1072 deletions
diff --git a/lib/adjective_query.cpp b/lib/adjective_query.cpp deleted file mode 100644 index 90ccef4..0000000 --- a/lib/adjective_query.cpp +++ /dev/null
@@ -1,1072 +0,0 @@
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.get_rhymes())
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::rhymes_with(rhyme _r)
50 {
51 _rhymes.push_back(_r);
52
53 return *this;
54 }
55
56 adjective_query& adjective_query::has_pronunciation()
57 {
58 this->_has_prn = true;
59
60 return *this;
61 }
62
63 adjective_query& adjective_query::has_rhyming_noun()
64 {
65 _has_rhyming_noun = true;
66
67 return *this;
68 }
69
70 adjective_query& adjective_query::has_rhyming_adjective()
71 {
72 _has_rhyming_adjective = true;
73
74 return *this;
75 }
76
77 adjective_query& adjective_query::has_rhyming_adverb()
78 {
79 _has_rhyming_adverb = true;
80
81 return *this;
82 }
83
84 adjective_query& adjective_query::has_rhyming_verb()
85 {
86 _has_rhyming_verb = true;
87
88 return *this;
89 }
90
91 adjective_query& adjective_query::with_stress(filter<std::vector<bool>> _arg)
92 {
93 _stress = _arg;
94
95 return *this;
96 }
97
98 adjective_query& adjective_query::with_prefix(filter<std::string> _f)
99 {
100 _f.clean();
101 _with_prefix = _f;
102
103 return *this;
104 }
105
106 adjective_query& adjective_query::with_suffix(filter<std::string> _f)
107 {
108 _f.clean();
109 _with_suffix = _f;
110
111 return *this;
112 }
113
114 adjective_query& adjective_query::with_complexity(int _arg)
115 {
116 _with_complexity = _arg;
117
118 return *this;
119 }
120
121 adjective_query& adjective_query::requires_comparative_form()
122 {
123 _requires_comparative_form = true;
124
125 return *this;
126 }
127
128 adjective_query& adjective_query::requires_superlative_form()
129 {
130 _requires_superlative_form = true;
131
132 return *this;
133 }
134
135 adjective_query& adjective_query::position(adjective::positioning pos)
136 {
137 _position = pos;
138
139 return *this;
140 }
141
142 adjective_query& adjective_query::is_variant()
143 {
144 this->_is_variant = true;
145
146 return *this;
147 }
148
149 adjective_query& adjective_query::variant_of(filter<noun> _f)
150 {
151 _f.clean();
152 _variant_of = _f;
153
154 return *this;
155 }
156
157 adjective_query& adjective_query::has_antonyms()
158 {
159 this->_is_antonymic = true;
160
161 return *this;
162 }
163
164 adjective_query& adjective_query::antonym_of(filter<adjective> _f)
165 {
166 _f.clean();
167 _antonym_of = _f;
168
169 return *this;
170 }
171
172 adjective_query& adjective_query::has_synonyms()
173 {
174 this->_is_synonymic = true;
175
176 return *this;
177 }
178
179 adjective_query& adjective_query::synonym_of(filter<adjective> _f)
180 {
181 _f.clean();
182 _synonym_of = _f;
183
184 return *this;
185 }
186
187 adjective_query& adjective_query::is_generalization()
188 {
189 this->_is_generalization = true;
190
191 return *this;
192 }
193
194 adjective_query& adjective_query::generalization_of(filter<adjective> _f)
195 {
196 _f.clean();
197 _generalization_of = _f;
198
199 return *this;
200 }
201
202 adjective_query& adjective_query::is_specification()
203 {
204 this->_is_specification = true;
205
206 return *this;
207 }
208
209 adjective_query& adjective_query::specification_of(filter<adjective> _f)
210 {
211 _f.clean();
212 _specification_of = _f;
213
214 return *this;
215 }
216
217 adjective_query& adjective_query::is_pertainymic()
218 {
219 this->_is_pertainymic = true;
220
221 return *this;
222 }
223
224 adjective_query& adjective_query::pertainym_of(filter<noun> _f)
225 {
226 _f.clean();
227 _pertainym_of = _f;
228
229 return *this;
230 }
231
232 adjective_query& adjective_query::is_mannernymic()
233 {
234 this->_is_mannernymic = true;
235
236 return *this;
237 }
238
239 adjective_query& adjective_query::anti_mannernym_of(filter<adverb> _f)
240 {
241 _f.clean();
242 _anti_mannernym_of = _f;
243
244 return *this;
245 }
246 /*
247 adjective_query& adjective_query::derived_from(const word& _w)
248 {
249 if (dynamic_cast<const adjective*>(&_w) != nullptr)
250 {
251 _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w));
252 } else if (dynamic_cast<const adverb*>(&_w) != nullptr)
253 {
254 _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w));
255 } else if (dynamic_cast<const noun*>(&_w) != nullptr)
256 {
257 _derived_from_noun.push_back(dynamic_cast<const noun&>(_w));
258 }
259
260 return *this;
261 }
262
263 adjective_query& adjective_query::not_derived_from(const word& _w)
264 {
265 if (dynamic_cast<const adjective*>(&_w) != nullptr)
266 {
267 _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w));
268 } else if (dynamic_cast<const adverb*>(&_w) != nullptr)
269 {
270 _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w));
271 } else if (dynamic_cast<const noun*>(&_w) != nullptr)
272 {
273 _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w));
274 }
275
276 return *this;
277 }
278 */
279 std::list<adjective> adjective_query::run() const
280 {
281 std::stringstream construct;
282 construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives";
283 std::list<std::string> conditions;
284 std::list<binding> bindings;
285
286 if (_has_prn)
287 {
288 conditions.push_back("adjective_id IN (SELECT adjective_id FROM adjective_pronunciations)");
289 }
290
291 if (!_rhymes.empty())
292 {
293 std::list<std::string> clauses(_rhymes.size(), "(prerhyme != ? AND rhyme = ?)");
294 std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
295 conditions.push_back(cond);
296
297 for (auto rhy : _rhymes)
298 {
299 bindings.emplace_back(rhy.get_prerhyme());
300 bindings.emplace_back(rhy.get_rhyme());
301 }
302 }
303
304 if (_has_rhyming_noun)
305 {
306 conditions.push_back("adjective_id IN (SELECT a.adjective_id FROM adjectives AS a INNER JOIN adjective_pronunciations AS curp ON curp.adjective_id = a.adjective_id INNER JOIN noun_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
307 }
308
309 if (_has_rhyming_adjective)
310 {
311 conditions.push_back("adjective_id IN (SELECT a.adjective_id FROM adjectives AS a INNER JOIN adjective_pronunciations AS curp ON curp.adjective_id = a.adjective_id INNER JOIN adjective_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme AND rhmp.adjective_id != curp.adjective_id)");
312 }
313
314 if (_has_rhyming_adverb)
315 {
316 conditions.push_back("adjective_id IN (SELECT a.adjective_id FROM adjectives AS a INNER JOIN adjective_pronunciations AS curp ON curp.adjective_id = a.adjective_id INNER JOIN adverb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
317 }
318
319 if (_has_rhyming_verb)
320 {
321 conditions.push_back("adjective_id IN (SELECT a.adjective_id FROM adjectives AS a INNER JOIN adjective_pronunciations AS curp ON curp.adjective_id = a.adjective_id INNER JOIN verb_pronunciations AS rhmp ON rhmp.prerhyme != curp.prerhyme AND rhmp.rhyme = curp.rhyme)");
322 }
323
324 for (auto except : _except)
325 {
326 conditions.push_back("adjective_id != ?");
327 bindings.emplace_back(except._id);
328 }
329
330 if (_requires_comparative_form)
331 {
332 conditions.push_back("comparative IS NOT NULL");
333 }
334
335 if (_requires_superlative_form)
336 {
337 conditions.push_back("superlative IS NOT NULL");
338 }
339
340 switch (_position)
341 {
342 case adjective::positioning::predicate: conditions.push_back("position = 'p'"); break;
343 case adjective::positioning::attributive: conditions.push_back("position = 'a'"); break;
344 case adjective::positioning::postnominal: conditions.push_back("position = 'i'"); break;
345 case adjective::positioning::undefined: break;
346 }
347
348 if (!_stress.empty())
349 {
350 std::stringstream cond;
351 if (_stress.get_notlogic())
352 {
353 cond << "adjective_id NOT IN";
354 } else {
355 cond << "adjective_id IN";
356 }
357
358 cond << "(SELECT adjective_id FROM adjective_pronunciations WHERE ";
359
360 std::function<std::string (filter<std::vector<bool>>, bool)> recur = [&] (filter<std::vector<bool>> f, bool notlogic) -> std::string {
361 switch (f.get_type())
362 {
363 case filter<std::vector<bool>>::type::singleton:
364 {
365 std::ostringstream _val;
366 for (auto syl : f.get_elem())
367 {
368 if (syl)
369 {
370 _val << "1";
371 } else {
372 _val << "0";
373 }
374 }
375
376 bindings.emplace_back(_val.str());
377
378 if (notlogic == f.get_notlogic())
379 {
380 return "stress = ?";
381 } else {
382 return "stress != ?";
383 }
384 }
385
386 case filter<std::vector<bool>>::type::group:
387 {
388 bool truelogic = notlogic != f.get_notlogic();
389
390 std::list<std::string> clauses;
391 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::vector<bool>> f2) {
392 return recur(f2, truelogic);
393 });
394
395 if (truelogic == f.get_orlogic())
396 {
397 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
398 } else {
399 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
400 }
401 }
402 }
403 };
404
405 cond << recur(_stress, _stress.get_notlogic());
406 cond << ")";
407 conditions.push_back(cond.str());
408 }
409
410 if (!_with_prefix.empty())
411 {
412 std::function<std::string (filter<std::string>, bool)> recur = [&] (filter<std::string> f, bool notlogic) -> std::string {
413 switch (f.get_type())
414 {
415 case filter<std::string>::type::singleton:
416 {
417 bindings.emplace_back(f.get_elem() + "%");
418
419 if (notlogic == f.get_notlogic())
420 {
421 return "base_form LIKE ?";
422 } else {
423 return "base_form NOT LIKE ?";
424 }
425 }
426
427 case filter<std::string>::type::group:
428 {
429 bool truelogic = notlogic != f.get_notlogic();
430
431 std::list<std::string> clauses;
432 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::string> f2) {
433 return recur(f2, truelogic);
434 });
435
436 if (truelogic == f.get_orlogic())
437 {
438 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
439 } else {
440 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
441 }
442 }
443 }
444 };
445
446 conditions.push_back(recur(_with_prefix, false));
447 }
448
449 if (!_with_suffix.empty())
450 {
451 std::function<std::string (filter<std::string>, bool)> recur = [&] (filter<std::string> f, bool notlogic) -> std::string {
452 switch (f.get_type())
453 {
454 case filter<std::string>::type::singleton:
455 {
456 bindings.emplace_back("%" + f.get_elem());
457
458 if (notlogic == f.get_notlogic())
459 {
460 return "base_form LIKE ?";
461 } else {
462 return "base_form NOT LIKE ?";
463 }
464 }
465
466 case filter<std::string>::type::group:
467 {
468 bool truelogic = notlogic != f.get_notlogic();
469
470 std::list<std::string> clauses;
471 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<std::string> f2) {
472 return recur(f2, truelogic);
473 });
474
475 if (truelogic == f.get_orlogic())
476 {
477 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
478 } else {
479 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
480 }
481 }
482 }
483 };
484
485 conditions.push_back(recur(_with_suffix, false));
486 }
487
488 if (_with_complexity != unlimited)
489 {
490 conditions.push_back("complexity = ?");
491 bindings.emplace_back(_with_complexity);
492 }
493
494 if (_is_variant)
495 {
496 conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)");
497 }
498
499 if (!_variant_of.empty())
500 {
501 std::stringstream cond;
502 if (_variant_of.get_notlogic())
503 {
504 cond << "adjective_id NOT IN";
505 } else {
506 cond << "adjective_id IN";
507 }
508
509 cond << "(SELECT adjective_id FROM variation WHERE ";
510
511 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
512 switch (f.get_type())
513 {
514 case filter<noun>::type::singleton:
515 {
516 bindings.emplace_back(f.get_elem()._id);
517
518 if (notlogic == f.get_notlogic())
519 {
520 return "noun_id = ?";
521 } else {
522 return "noun_id != ?";
523 }
524 }
525
526 case filter<noun>::type::group:
527 {
528 bool truelogic = notlogic != f.get_notlogic();
529
530 std::list<std::string> clauses;
531 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
532 return recur(f2, truelogic);
533 });
534
535 if (truelogic == f.get_orlogic())
536 {
537 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
538 } else {
539 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
540 }
541 }
542 }
543 };
544
545 cond << recur(_variant_of, _variant_of.get_notlogic());
546 cond << ")";
547 conditions.push_back(cond.str());
548 }
549
550 if (_is_antonymic)
551 {
552 conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)");
553 }
554
555 if (!_antonym_of.empty())
556 {
557 std::stringstream cond;
558 if (_antonym_of.get_notlogic())
559 {
560 cond << "adjective_id NOT IN";
561 } else {
562 cond << "adjective_id IN";
563 }
564
565 cond << "(SELECT adjective_2_id FROM adjective_antonymy WHERE ";
566
567 std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string {
568 switch (f.get_type())
569 {
570 case filter<adjective>::type::singleton:
571 {
572 bindings.emplace_back(f.get_elem()._id);
573
574 if (notlogic == f.get_notlogic())
575 {
576 return "adjective_1_id = ?";
577 } else {
578 return "adjective_1_id != ?";
579 }
580 }
581
582 case filter<adjective>::type::group:
583 {
584 bool truelogic = notlogic != f.get_notlogic();
585
586 std::list<std::string> clauses;
587 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) {
588 return recur(f2, truelogic);
589 });
590
591 if (truelogic == f.get_orlogic())
592 {
593 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
594 } else {
595 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
596 }
597 }
598 }
599 };
600
601 cond << recur(_antonym_of, _antonym_of.get_notlogic());
602 cond << ")";
603 conditions.push_back(cond.str());
604 }
605
606 if (_is_synonymic)
607 {
608 conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)");
609 }
610
611 if (!_synonym_of.empty())
612 {
613 std::stringstream cond;
614 if (_synonym_of.get_notlogic())
615 {
616 cond << "adjective_id NOT IN";
617 } else {
618 cond << "adjective_id IN";
619 }
620
621 cond << "(SELECT adjective_2_id FROM adjective_synonymy WHERE ";
622
623 std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string {
624 switch (f.get_type())
625 {
626 case filter<adjective>::type::singleton:
627 {
628 bindings.emplace_back(f.get_elem()._id);
629
630 if (notlogic == f.get_notlogic())
631 {
632 return "adjective_1_id = ?";
633 } else {
634 return "adjective_1_id != ?";
635 }
636 }
637
638 case filter<adjective>::type::group:
639 {
640 bool truelogic = notlogic != f.get_notlogic();
641
642 std::list<std::string> clauses;
643 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) {
644 return recur(f2, truelogic);
645 });
646
647 if (truelogic == f.get_orlogic())
648 {
649 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
650 } else {
651 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
652 }
653 }
654 }
655 };
656
657 cond << recur(_synonym_of, _synonym_of.get_notlogic());
658 cond << ")";
659 conditions.push_back(cond.str());
660 }
661
662 if (_is_generalization)
663 {
664 conditions.push_back("adjective_id IN (SELECT general_id FROM specification)");
665 }
666
667 if (!_generalization_of.empty())
668 {
669 std::stringstream cond;
670 if (_generalization_of.get_notlogic())
671 {
672 cond << "adjective_id NOT IN";
673 } else {
674 cond << "adjective_id IN";
675 }
676
677 cond << "(SELECT general_id FROM specification WHERE ";
678
679 std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string {
680 switch (f.get_type())
681 {
682 case filter<adjective>::type::singleton:
683 {
684 bindings.emplace_back(f.get_elem()._id);
685
686 if (notlogic == f.get_notlogic())
687 {
688 return "specific_id = ?";
689 } else {
690 return "specific_id != ?";
691 }
692 }
693
694 case filter<adjective>::type::group:
695 {
696 bool truelogic = notlogic != f.get_notlogic();
697
698 std::list<std::string> clauses;
699 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) {
700 return recur(f2, truelogic);
701 });
702
703 if (truelogic == f.get_orlogic())
704 {
705 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
706 } else {
707 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
708 }
709 }
710 }
711 };
712
713 cond << recur(_generalization_of, _generalization_of.get_notlogic());
714 cond << ")";
715 conditions.push_back(cond.str());
716 }
717
718 if (_is_specification)
719 {
720 conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)");
721 }
722
723 if (!_specification_of.empty())
724 {
725 std::stringstream cond;
726 if (_specification_of.get_notlogic())
727 {
728 cond << "adjective_id NOT IN";
729 } else {
730 cond << "adjective_id IN";
731 }
732
733 cond << "(SELECT specific_id FROM specification WHERE ";
734
735 std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string {
736 switch (f.get_type())
737 {
738 case filter<adjective>::type::singleton:
739 {
740 bindings.emplace_back(f.get_elem()._id);
741
742 if (notlogic == f.get_notlogic())
743 {
744 return "general_id = ?";
745 } else {
746 return "general_id != ?";
747 }
748 }
749
750 case filter<adjective>::type::group:
751 {
752 bool truelogic = notlogic != f.get_notlogic();
753
754 std::list<std::string> clauses;
755 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) {
756 return recur(f2, truelogic);
757 });
758
759 if (truelogic == f.get_orlogic())
760 {
761 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
762 } else {
763 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
764 }
765 }
766 }
767 };
768
769 cond << recur(_specification_of, _specification_of.get_notlogic());
770 cond << ")";
771 conditions.push_back(cond.str());
772 }
773
774 if (_is_pertainymic)
775 {
776 conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)");
777 }
778
779 if (!_pertainym_of.empty())
780 {
781 std::stringstream cond;
782 if (_pertainym_of.get_notlogic())
783 {
784 cond << "adjective_id NOT IN";
785 } else {
786 cond << "adjective_id IN";
787 }
788
789 cond << "(SELECT pertainym_id FROM pertainymy WHERE ";
790
791 std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string {
792 switch (f.get_type())
793 {
794 case filter<noun>::type::singleton:
795 {
796 bindings.emplace_back(f.get_elem()._id);
797
798 if (notlogic == f.get_notlogic())
799 {
800 return "noun_id = ?";
801 } else {
802 return "noun_id != ?";
803 }
804 }
805
806 case filter<noun>::type::group:
807 {
808 bool truelogic = notlogic != f.get_notlogic();
809
810 std::list<std::string> clauses;
811 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) {
812 return recur(f2, truelogic);
813 });
814
815 if (truelogic == f.get_orlogic())
816 {
817 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
818 } else {
819 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
820 }
821 }
822 }
823 };
824
825 cond << recur(_pertainym_of, _pertainym_of.get_notlogic());
826 cond << ")";
827 conditions.push_back(cond.str());
828 }
829
830 if (_is_mannernymic)
831 {
832 conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)");
833 }
834
835 if (!_anti_mannernym_of.empty())
836 {
837 std::stringstream cond;
838 if (_anti_mannernym_of.get_notlogic())
839 {
840 cond << "adjective_id NOT IN";
841 } else {
842 cond << "adjective_id IN";
843 }
844
845 cond << "(SELECT adjective_id FROM mannernymy WHERE ";
846
847 std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string {
848 switch (f.get_type())
849 {
850 case filter<adverb>::type::singleton:
851 {
852 bindings.emplace_back(f.get_elem()._id);
853
854 if (notlogic == f.get_notlogic())
855 {
856 return "mannernym_id = ?";
857 } else {
858 return "mannernym_id != ?";
859 }
860 }
861
862 case filter<adverb>::type::group:
863 {
864 bool truelogic = notlogic != f.get_notlogic();
865
866 std::list<std::string> clauses;
867 std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) {
868 return recur(f2, truelogic);
869 });
870
871 if (truelogic == f.get_orlogic())
872 {
873 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")";
874 } else {
875 return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
876 }
877 }
878 }
879 };
880
881 cond << recur(_anti_mannernym_of, _anti_mannernym_of.get_notlogic());
882 cond << ")";
883 conditions.push_back(cond.str());
884 }
885/*
886 if (!_derived_from_adjective.empty())
887 {
888 std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_2_id = @DERADJ");
889 std::string cond = "adjective_id IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
890 conditions.push_back(cond);
891 }
892
893 if (!_not_derived_from_adjective.empty())
894 {
895 std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_2_id = @NDERADJ");
896 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 ") + ")";
897 conditions.push_back(cond);
898 }
899
900 if (!_derived_from_adverb.empty())
901 {
902 std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV");
903 std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
904 conditions.push_back(cond);
905 }
906
907 if (!_not_derived_from_adverb.empty())
908 {
909 std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV");
910 std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
911 conditions.push_back(cond);
912 }
913
914 if (!_derived_from_noun.empty())
915 {
916 std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN");
917 std::string cond = "adjective_id IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
918 conditions.push_back(cond);
919 }
920
921 if (!_not_derived_from_noun.empty())
922 {
923 std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN");
924 std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
925 conditions.push_back(cond);
926 }*/
927
928 if (!conditions.empty())
929 {
930 construct << " WHERE ";
931 construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND ");
932 }
933
934 if (_random)
935 {
936 construct << " ORDER BY RANDOM()";
937 }
938
939 if (_limit != unlimited)
940 {
941 construct << " LIMIT " << _limit;
942 }
943
944 sqlite3_stmt* ppstmt;
945 std::string query = construct.str();
946 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
947 {
948 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
949 }
950
951 int i = 1;
952 for (auto& binding : bindings)
953 {
954 switch (binding.get_type())
955 {
956 case binding::type::integer:
957 {
958 sqlite3_bind_int(ppstmt, i, binding.get_integer());
959
960 break;
961 }
962
963 case binding::type::string:
964 {
965 sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT);
966
967 break;
968 }
969 }
970
971 i++;
972 }
973
974 /*
975 for (auto adj : _derived_from_adjective)
976 {
977 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id);
978 }
979
980 for (auto adj : _not_derived_from_adjective)
981 {
982 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id);
983 }
984
985 for (auto adv : _derived_from_adverb)
986 {
987 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id);
988 }
989
990 for (auto adv : _not_derived_from_adverb)
991 {
992 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id);
993 }
994
995 for (auto n : _derived_from_noun)
996 {
997 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id);
998 }
999
1000 for (auto n : _not_derived_from_noun)
1001 {
1002 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id);
1003 }
1004*/
1005 std::list<adjective> output;
1006 while (sqlite3_step(ppstmt) == SQLITE_ROW)
1007 {
1008 adjective tnc {_data, sqlite3_column_int(ppstmt, 0)};
1009 tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
1010
1011 if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL)
1012 {
1013 tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
1014 }
1015
1016 if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL)
1017 {
1018 tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3)));
1019 }
1020
1021 if (sqlite3_column_type(ppstmt, 4) != SQLITE_NULL)
1022 {
1023 std::string adjpos(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4)));
1024 if (adjpos == "p")
1025 {
1026 tnc._position = adjective::positioning::predicate;
1027 } else if (adjpos == "a")
1028 {
1029 tnc._position = adjective::positioning::attributive;
1030 } else if (adjpos == "i")
1031 {
1032 tnc._position = adjective::positioning::postnominal;
1033 }
1034 }
1035
1036 output.push_back(tnc);
1037 }
1038
1039 sqlite3_finalize(ppstmt);
1040
1041 for (auto& adjective : output)
1042 {
1043 query = "SELECT pronunciation, prerhyme, rhyme FROM adjective_pronunciations WHERE adjective_id = ?";
1044 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
1045 {
1046 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
1047 }
1048
1049 sqlite3_bind_int(ppstmt, 1, adjective._id);
1050
1051 while (sqlite3_step(ppstmt) == SQLITE_ROW)
1052 {
1053 std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0)));
1054 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
1055
1056 adjective.pronunciations.push_back(phonemes);
1057
1058 if ((sqlite3_column_type(ppstmt, 1) != SQLITE_NULL) && (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL))
1059 {
1060 std::string prerhyme(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
1061 std::string rhyming(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
1062 adjective.rhymes.emplace_back(prerhyme, rhyming);
1063 }
1064 }
1065
1066 sqlite3_finalize(ppstmt);
1067 }
1068
1069 return output;
1070 }
1071
1072};