diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/adjective.cpp | 655 | ||||
-rw-r--r-- | lib/adjective.h | 94 | ||||
-rw-r--r-- | lib/adjective_query.cpp | 819 | ||||
-rw-r--r-- | lib/adjective_query.h | 91 | ||||
-rw-r--r-- | lib/adverb.cpp | 443 | ||||
-rw-r--r-- | lib/adverb.h | 62 | ||||
-rw-r--r-- | lib/adverb_query.cpp | 514 | ||||
-rw-r--r-- | lib/adverb_query.h | 65 | ||||
-rw-r--r-- | lib/c++14.h | 35 | ||||
-rw-r--r-- | lib/data.cpp | 12 | ||||
-rw-r--r-- | lib/data.h | 299 | ||||
-rw-r--r-- | lib/frame.cpp | 320 | ||||
-rw-r--r-- | lib/frame.h | 118 | ||||
-rw-r--r-- | lib/frame_query.cpp | 142 | ||||
-rw-r--r-- | lib/frame_query.h | 21 | ||||
-rw-r--r-- | lib/noun.cpp | 1010 | ||||
-rw-r--r-- | lib/noun.h | 150 | ||||
-rw-r--r-- | lib/noun_query.cpp | 1453 | ||||
-rw-r--r-- | lib/noun_query.h | 139 | ||||
-rw-r--r-- | lib/preposition.cpp | 83 | ||||
-rw-r--r-- | lib/preposition.h | 38 | ||||
-rw-r--r-- | lib/token.cpp | 617 | ||||
-rw-r--r-- | lib/token.h | 413 | ||||
-rw-r--r-- | lib/util.h | 8 | ||||
-rw-r--r-- | lib/verb.cpp | 169 | ||||
-rw-r--r-- | lib/verb.h | 45 | ||||
-rw-r--r-- | lib/verb_query.cpp | 170 | ||||
-rw-r--r-- | lib/verb_query.h | 34 | ||||
-rw-r--r-- | lib/verbly.h | 25 | ||||
-rw-r--r-- | lib/word.cpp | 11 | ||||
-rw-r--r-- | lib/word.h | 13 |
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 | ||
3 | namespace verbly { | 3 | namespace verbly { |
4 | 4 | ||
5 | adjective::adjective() | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
5 | adjective::adjective(const data& _data, int _id) : word(_data, _id) | 10 | adjective::adjective(const data& _data, int _id) : word(_data, _id) |
6 | { | 11 | { |
7 | 12 | ||
@@ -9,682 +14,100 @@ namespace verbly { | |||
9 | 14 | ||
10 | std::string adjective::base_form() const | 15 | std::string adjective::base_form() const |
11 | { | 16 | { |
17 | assert(_valid == true); | ||
18 | |||
12 | return _base_form; | 19 | return _base_form; |
13 | } | 20 | } |
14 | 21 | ||
15 | std::string adjective::comparative_form() const | 22 | std::string adjective::comparative_form() const |
16 | { | 23 | { |
24 | assert(_valid == true); | ||
25 | |||
17 | return _comparative_form; | 26 | return _comparative_form; |
18 | } | 27 | } |
19 | 28 | ||
20 | std::string adjective::superlative_form() const | 29 | std::string adjective::superlative_form() const |
21 | { | 30 | { |
31 | assert(_valid == true); | ||
32 | |||
22 | return _superlative_form; | 33 | return _superlative_form; |
23 | } | 34 | } |
24 | 35 | ||
25 | adjective::positioning adjective::position() const | 36 | adjective::positioning adjective::position() const |
26 | { | 37 | { |
38 | assert(_valid == true); | ||
39 | |||
27 | return _position; | 40 | return _position; |
28 | } | 41 | } |
29 | 42 | ||
30 | bool adjective::has_comparative_form() const | 43 | bool adjective::has_comparative_form() const |
31 | { | 44 | { |
45 | assert(_valid == true); | ||
46 | |||
32 | return !_comparative_form.empty(); | 47 | return !_comparative_form.empty(); |
33 | } | 48 | } |
34 | 49 | ||
35 | bool adjective::has_superlative_form() const | 50 | bool adjective::has_superlative_form() const |
36 | { | 51 | { |
52 | assert(_valid == true); | ||
53 | |||
37 | return !_superlative_form.empty(); | 54 | return !_superlative_form.empty(); |
38 | } | 55 | } |
39 | 56 | ||
40 | bool adjective::has_position() const | 57 | bool adjective::has_position() const |
41 | { | 58 | { |
59 | assert(_valid == true); | ||
60 | |||
42 | return _position != adjective::positioning::undefined; | 61 | return _position != adjective::positioning::undefined; |
43 | } | 62 | } |
44 | 63 | ||
45 | adjective_query adjective::antonyms() const | 64 | adjective_query adjective::antonyms() const |
46 | { | 65 | { |
47 | return _data.adjectives().antonym_of(*this); | 66 | assert(_valid == true); |
48 | } | ||
49 | |||
50 | adjective_query adjective::synonyms() const | ||
51 | { | ||
52 | return _data.adjectives().synonym_of(*this); | ||
53 | } | ||
54 | |||
55 | adjective_query adjective::generalizations() const | ||
56 | { | ||
57 | return _data.adjectives().generalization_of(*this); | ||
58 | } | ||
59 | |||
60 | adjective_query adjective::specifications() const | ||
61 | { | ||
62 | return _data.adjectives().specification_of(*this); | ||
63 | } | ||
64 | |||
65 | noun_query adjective::anti_pertainyms() const | ||
66 | { | ||
67 | return _data.nouns().anti_pertainym_of(*this); | ||
68 | } | ||
69 | |||
70 | adverb_query adjective::mannernyms() const | ||
71 | { | ||
72 | return _data.adverbs().mannernym_of(*this); | ||
73 | } | ||
74 | |||
75 | noun_query adjective::attributes() const | ||
76 | { | ||
77 | return _data.nouns().attribute_of(*this); | ||
78 | } | ||
79 | |||
80 | adjective_query::adjective_query(const data& _data) : _data(_data) | ||
81 | { | ||
82 | |||
83 | } | ||
84 | |||
85 | adjective_query& adjective_query::limit(int _limit) | ||
86 | { | ||
87 | if ((_limit > 0) || (_limit == unlimited)) | ||
88 | { | ||
89 | this->_limit = _limit; | ||
90 | } | ||
91 | |||
92 | return *this; | ||
93 | } | ||
94 | |||
95 | adjective_query& adjective_query::random(bool _random) | ||
96 | { | ||
97 | this->_random = _random; | ||
98 | |||
99 | return *this; | ||
100 | } | ||
101 | |||
102 | adjective_query& adjective_query::except(const adjective& _word) | ||
103 | { | ||
104 | _except.push_back(_word); | ||
105 | |||
106 | return *this; | ||
107 | } | ||
108 | |||
109 | adjective_query& adjective_query::rhymes_with(const word& _word) | ||
110 | { | ||
111 | for (auto rhyme : _word.rhyme_phonemes()) | ||
112 | { | ||
113 | _rhymes.push_back(rhyme); | ||
114 | } | ||
115 | |||
116 | if (dynamic_cast<const adjective*>(&_word) != nullptr) | ||
117 | { | ||
118 | _except.push_back(dynamic_cast<const adjective&>(_word)); | ||
119 | } | ||
120 | |||
121 | return *this; | ||
122 | } | ||
123 | |||
124 | adjective_query& adjective_query::has_pronunciation(bool _has_prn) | ||
125 | { | ||
126 | this->_has_prn = _has_prn; | ||
127 | |||
128 | return *this; | ||
129 | } | ||
130 | |||
131 | adjective_query& adjective_query::is_variant(bool _is_variant) | ||
132 | { | ||
133 | this->_is_variant = _is_variant; | ||
134 | |||
135 | return *this; | ||
136 | } | ||
137 | |||
138 | adjective_query& adjective_query::variant_of(const noun& _noun) | ||
139 | { | ||
140 | _variant_of.push_back(_noun); | ||
141 | |||
142 | return *this; | ||
143 | } | ||
144 | |||
145 | adjective_query& adjective_query::not_variant_of(const noun& _noun) | ||
146 | { | ||
147 | _not_variant_of.push_back(_noun); | ||
148 | |||
149 | return *this; | ||
150 | } | ||
151 | |||
152 | adjective_query& adjective_query::has_antonyms(bool _is_antonymic) | ||
153 | { | ||
154 | this->_is_antonymic = _is_antonymic; | ||
155 | |||
156 | return *this; | ||
157 | } | ||
158 | |||
159 | adjective_query& adjective_query::antonym_of(const adjective& _adj) | ||
160 | { | ||
161 | _antonym_of.push_back(_adj); | ||
162 | |||
163 | return *this; | ||
164 | } | ||
165 | |||
166 | adjective_query& adjective_query::not_antonym_of(const adjective& _adj) | ||
167 | { | ||
168 | _not_antonym_of.push_back(_adj); | ||
169 | |||
170 | return *this; | ||
171 | } | ||
172 | |||
173 | adjective_query& adjective_query::has_synonyms(bool _is_synonymic) | ||
174 | { | ||
175 | this->_is_synonymic = _is_synonymic; | ||
176 | |||
177 | return *this; | ||
178 | } | ||
179 | |||
180 | adjective_query& adjective_query::synonym_of(const adjective& _adj) | ||
181 | { | ||
182 | _synonym_of.push_back(_adj); | ||
183 | |||
184 | return *this; | ||
185 | } | ||
186 | |||
187 | adjective_query& adjective_query::not_synonym_of(const adjective& _adj) | ||
188 | { | ||
189 | _not_synonym_of.push_back(_adj); | ||
190 | |||
191 | return *this; | ||
192 | } | ||
193 | |||
194 | adjective_query& adjective_query::is_generalization(bool _is_generalization) | ||
195 | { | ||
196 | this->_is_generalization = _is_generalization; | ||
197 | |||
198 | return *this; | ||
199 | } | ||
200 | |||
201 | adjective_query& adjective_query::generalization_of(const adjective& _adj) | ||
202 | { | ||
203 | _generalization_of.push_back(_adj); | ||
204 | |||
205 | return *this; | ||
206 | } | ||
207 | |||
208 | adjective_query& adjective_query::not_generalization_of(const adjective& _adj) | ||
209 | { | ||
210 | _not_generalization_of.push_back(_adj); | ||
211 | |||
212 | return *this; | ||
213 | } | ||
214 | |||
215 | adjective_query& adjective_query::is_specification(bool _is_specification) | ||
216 | { | ||
217 | this->_is_specification = _is_specification; | ||
218 | |||
219 | return *this; | ||
220 | } | ||
221 | |||
222 | adjective_query& adjective_query::specification_of(const adjective& _adj) | ||
223 | { | ||
224 | _specification_of.push_back(_adj); | ||
225 | 67 | ||
226 | return *this; | 68 | return _data->adjectives().antonym_of(*this); |
227 | } | 69 | } |
228 | 70 | ||
229 | adjective_query& adjective_query::not_specification_of(const adjective& _adj) | 71 | adjective_query adjective::synonyms() const |
230 | { | ||
231 | _not_specification_of.push_back(_adj); | ||
232 | |||
233 | return *this; | ||
234 | } | ||
235 | |||
236 | adjective_query& adjective_query::is_pertainymic(bool _is_pertainymic) | ||
237 | { | ||
238 | this->_is_pertainymic = _is_pertainymic; | ||
239 | |||
240 | return *this; | ||
241 | } | ||
242 | |||
243 | adjective_query& adjective_query::pertainym_of(const noun& _noun) | ||
244 | { | 72 | { |
245 | _pertainym_of.push_back(_noun); | 73 | assert(_valid == true); |
246 | 74 | ||
247 | return *this; | 75 | return _data->adjectives().synonym_of(*this); |
248 | } | 76 | } |
249 | 77 | ||
250 | adjective_query& adjective_query::is_mannernymic(bool _is_mannernymic) | 78 | adjective_query adjective::generalizations() const |
251 | { | 79 | { |
252 | this->_is_mannernymic = _is_mannernymic; | 80 | assert(_valid == true); |
253 | 81 | ||
254 | return *this; | 82 | return _data->adjectives().generalization_of(*this); |
255 | } | 83 | } |
256 | 84 | ||
257 | adjective_query& adjective_query::anti_mannernym_of(const adverb& _adv) | 85 | adjective_query adjective::specifications() const |
258 | { | 86 | { |
259 | _anti_mannernym_of.push_back(_adv); | 87 | assert(_valid == true); |
260 | 88 | ||
261 | return *this; | 89 | return _data->adjectives().specification_of(*this); |
262 | } | 90 | } |
263 | 91 | ||
264 | adjective_query& adjective_query::derived_from(const word& _w) | 92 | noun_query adjective::anti_pertainyms() const |
265 | { | 93 | { |
266 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 94 | assert(_valid == true); |
267 | { | ||
268 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
269 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
270 | { | ||
271 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
272 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
273 | { | ||
274 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
275 | } | ||
276 | 95 | ||
277 | return *this; | 96 | return _data->nouns().anti_pertainym_of(*this); |
278 | } | 97 | } |
279 | 98 | ||
280 | adjective_query& adjective_query::not_derived_from(const word& _w) | 99 | adverb_query adjective::mannernyms() const |
281 | { | 100 | { |
282 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 101 | assert(_valid == true); |
283 | { | ||
284 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
285 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
286 | { | ||
287 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
288 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
289 | { | ||
290 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
291 | } | ||
292 | 102 | ||
293 | return *this; | 103 | return _data->adverbs().mannernym_of(*this); |
294 | } | 104 | } |
295 | 105 | ||
296 | std::list<adjective> adjective_query::run() const | 106 | noun_query adjective::attributes() const |
297 | { | 107 | { |
298 | std::stringstream construct; | 108 | assert(_valid == true); |
299 | construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; | ||
300 | std::list<std::string> conditions; | ||
301 | |||
302 | if (_has_prn) | ||
303 | { | ||
304 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM adjective_pronunciations)"); | ||
305 | } | ||
306 | |||
307 | if (!_rhymes.empty()) | ||
308 | { | ||
309 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
310 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
311 | conditions.push_back(cond); | ||
312 | } | ||
313 | |||
314 | for (auto except : _except) | ||
315 | { | ||
316 | conditions.push_back("adjective_id != @EXCID"); | ||
317 | } | ||
318 | |||
319 | if (_requires_comparative_form) | ||
320 | { | ||
321 | conditions.push_back("comparative IS NOT NULL"); | ||
322 | } | ||
323 | |||
324 | if (_requires_superlative_form) | ||
325 | { | ||
326 | conditions.push_back("superlative IS NOT NULL"); | ||
327 | } | ||
328 | |||
329 | if (_position != adjective::positioning::undefined) | ||
330 | { | ||
331 | switch (_position) | ||
332 | { | ||
333 | case adjective::positioning::predicate: conditions.push_back("position = 'p'"); break; | ||
334 | case adjective::positioning::attributive: conditions.push_back("position = 'a'"); break; | ||
335 | case adjective::positioning::postnominal: conditions.push_back("position = 'i'"); break; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | if (_is_variant) | ||
340 | { | ||
341 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)"); | ||
342 | } | ||
343 | |||
344 | if (!_variant_of.empty()) | ||
345 | { | ||
346 | std::list<std::string> clauses(_variant_of.size(), "noun_id = @ATTRID"); | ||
347 | std::string cond = "adjective_id IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
348 | conditions.push_back(cond); | ||
349 | } | ||
350 | |||
351 | if (!_not_variant_of.empty()) | ||
352 | { | ||
353 | std::list<std::string> clauses(_not_variant_of.size(), "noun_id = @NATTRID"); | ||
354 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
355 | conditions.push_back(cond); | ||
356 | } | ||
357 | |||
358 | if (_is_antonymic) | ||
359 | { | ||
360 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); | ||
361 | } | ||
362 | |||
363 | if (!_antonym_of.empty()) | ||
364 | { | ||
365 | std::list<std::string> clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); | ||
366 | std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
367 | conditions.push_back(cond); | ||
368 | } | ||
369 | |||
370 | if (!_not_antonym_of.empty()) | ||
371 | { | ||
372 | std::list<std::string> clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); | ||
373 | std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
374 | conditions.push_back(cond); | ||
375 | } | ||
376 | 109 | ||
377 | if (_is_synonymic) | 110 | return _data->nouns().attribute_of(*this); |
378 | { | ||
379 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); | ||
380 | } | ||
381 | |||
382 | if (!_synonym_of.empty()) | ||
383 | { | ||
384 | std::list<std::string> clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); | ||
385 | std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
386 | conditions.push_back(cond); | ||
387 | } | ||
388 | |||
389 | if (!_not_synonym_of.empty()) | ||
390 | { | ||
391 | std::list<std::string> clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); | ||
392 | std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
393 | conditions.push_back(cond); | ||
394 | } | ||
395 | |||
396 | if (_is_generalization) | ||
397 | { | ||
398 | conditions.push_back("adjective_id IN (SELECT general_id FROM specification)"); | ||
399 | } | ||
400 | |||
401 | if (!_generalization_of.empty()) | ||
402 | { | ||
403 | std::list<std::string> clauses(_generalization_of.size(), "specific_id = @SPECID"); | ||
404 | std::string cond = "adjective_id IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
405 | conditions.push_back(cond); | ||
406 | } | ||
407 | |||
408 | if (!_not_generalization_of.empty()) | ||
409 | { | ||
410 | std::list<std::string> clauses(_not_generalization_of.size(), "specific_id = @NSPECID"); | ||
411 | std::string cond = "adjective_id NOT IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
412 | conditions.push_back(cond); | ||
413 | } | ||
414 | |||
415 | if (_is_specification) | ||
416 | { | ||
417 | conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)"); | ||
418 | } | ||
419 | |||
420 | if (!_specification_of.empty()) | ||
421 | { | ||
422 | std::list<std::string> clauses(_specification_of.size(), "general_id = @GENID"); | ||
423 | std::string cond = "adjective_id IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
424 | conditions.push_back(cond); | ||
425 | } | ||
426 | |||
427 | if (!_not_specification_of.empty()) | ||
428 | { | ||
429 | std::list<std::string> clauses(_not_specification_of.size(), "general_id = @NGENID"); | ||
430 | std::string cond = "adjective_id NOT IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
431 | conditions.push_back(cond); | ||
432 | } | ||
433 | |||
434 | if (_is_pertainymic) | ||
435 | { | ||
436 | conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)"); | ||
437 | } | ||
438 | |||
439 | if (!_pertainym_of.empty()) | ||
440 | { | ||
441 | std::list<std::string> clauses(_pertainym_of.size(), "noun_id = @APERID"); | ||
442 | std::string cond = "adjective_id IN (SELECT pertainym_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
443 | conditions.push_back(cond); | ||
444 | } | ||
445 | |||
446 | if (_is_mannernymic) | ||
447 | { | ||
448 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)"); | ||
449 | } | ||
450 | |||
451 | if (!_anti_mannernym_of.empty()) | ||
452 | { | ||
453 | std::list<std::string> clauses(_anti_mannernym_of.size(), "mannernym_id = @MANID"); | ||
454 | std::string cond = "adjective_id IN (SELECT adjective_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
455 | conditions.push_back(cond); | ||
456 | } | ||
457 | |||
458 | if (!_derived_from_adjective.empty()) | ||
459 | { | ||
460 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_2_id = @DERADJ"); | ||
461 | std::string cond = "adjective_id IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
462 | conditions.push_back(cond); | ||
463 | } | ||
464 | |||
465 | if (!_not_derived_from_adjective.empty()) | ||
466 | { | ||
467 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_2_id = @NDERADJ"); | ||
468 | std::string cond = "adjective_id NOT IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
469 | conditions.push_back(cond); | ||
470 | } | ||
471 | |||
472 | if (!_derived_from_adverb.empty()) | ||
473 | { | ||
474 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); | ||
475 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
476 | conditions.push_back(cond); | ||
477 | } | ||
478 | |||
479 | if (!_not_derived_from_adverb.empty()) | ||
480 | { | ||
481 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); | ||
482 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
483 | conditions.push_back(cond); | ||
484 | } | ||
485 | |||
486 | if (!_derived_from_noun.empty()) | ||
487 | { | ||
488 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN"); | ||
489 | std::string cond = "adjective_id IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
490 | conditions.push_back(cond); | ||
491 | } | ||
492 | |||
493 | if (!_not_derived_from_noun.empty()) | ||
494 | { | ||
495 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); | ||
496 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
497 | conditions.push_back(cond); | ||
498 | } | ||
499 | |||
500 | if (!conditions.empty()) | ||
501 | { | ||
502 | construct << " WHERE "; | ||
503 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
504 | } | ||
505 | |||
506 | if (_random) | ||
507 | { | ||
508 | construct << " ORDER BY RANDOM()"; | ||
509 | } | ||
510 | |||
511 | if (_limit != unlimited) | ||
512 | { | ||
513 | construct << " LIMIT " << _limit; | ||
514 | } | ||
515 | |||
516 | sqlite3_stmt* ppstmt; | ||
517 | std::string query = construct.str(); | ||
518 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
519 | { | ||
520 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
521 | } | ||
522 | |||
523 | if (!_rhymes.empty()) | ||
524 | { | ||
525 | int i = 0; | ||
526 | for (auto rhyme : _rhymes) | ||
527 | { | ||
528 | std::string rhymer = "%" + rhyme; | ||
529 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
530 | |||
531 | i++; | ||
532 | } | ||
533 | } | ||
534 | |||
535 | for (auto except : _except) | ||
536 | { | ||
537 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
538 | } | ||
539 | |||
540 | for (auto attribute : _variant_of) | ||
541 | { | ||
542 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ATTRID"), attribute._id); | ||
543 | } | ||
544 | |||
545 | for (auto attribute : _not_variant_of) | ||
546 | { | ||
547 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NATTRID"), attribute._id); | ||
548 | } | ||
549 | |||
550 | for (auto antonym : _antonym_of) | ||
551 | { | ||
552 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
553 | } | ||
554 | |||
555 | for (auto antonym : _not_antonym_of) | ||
556 | { | ||
557 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
558 | } | ||
559 | |||
560 | for (auto synonym : _synonym_of) | ||
561 | { | ||
562 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
563 | } | ||
564 | |||
565 | for (auto synonym : _not_synonym_of) | ||
566 | { | ||
567 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
568 | } | ||
569 | |||
570 | for (auto specific : _generalization_of) | ||
571 | { | ||
572 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SPECID"), specific._id); | ||
573 | } | ||
574 | |||
575 | for (auto specific : _not_generalization_of) | ||
576 | { | ||
577 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSPECID"), specific._id); | ||
578 | } | ||
579 | |||
580 | for (auto general : _specification_of) | ||
581 | { | ||
582 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GENID"), general._id); | ||
583 | } | ||
584 | |||
585 | for (auto general : _not_specification_of) | ||
586 | { | ||
587 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NGENID"), general._id); | ||
588 | } | ||
589 | |||
590 | for (auto n : _pertainym_of) | ||
591 | { | ||
592 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@APERID"), n._id); | ||
593 | } | ||
594 | |||
595 | for (auto mannernym : _anti_mannernym_of) | ||
596 | { | ||
597 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MANID"), mannernym._id); | ||
598 | } | ||
599 | |||
600 | for (auto adj : _derived_from_adjective) | ||
601 | { | ||
602 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
603 | } | ||
604 | |||
605 | for (auto adj : _not_derived_from_adjective) | ||
606 | { | ||
607 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
608 | } | ||
609 | |||
610 | for (auto adv : _derived_from_adverb) | ||
611 | { | ||
612 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
613 | } | ||
614 | |||
615 | for (auto adv : _not_derived_from_adverb) | ||
616 | { | ||
617 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
618 | } | ||
619 | |||
620 | for (auto n : _derived_from_noun) | ||
621 | { | ||
622 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
623 | } | ||
624 | |||
625 | for (auto n : _not_derived_from_noun) | ||
626 | { | ||
627 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
628 | } | ||
629 | |||
630 | std::list<adjective> output; | ||
631 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
632 | { | ||
633 | adjective tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
634 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
635 | |||
636 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
637 | { | ||
638 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
639 | } | ||
640 | |||
641 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
642 | { | ||
643 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
644 | } | ||
645 | |||
646 | if (sqlite3_column_type(ppstmt, 4) != SQLITE_NULL) | ||
647 | { | ||
648 | std::string adjpos(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
649 | if (adjpos == "p") | ||
650 | { | ||
651 | tnc._position = adjective::positioning::predicate; | ||
652 | } else if (adjpos == "a") | ||
653 | { | ||
654 | tnc._position = adjective::positioning::attributive; | ||
655 | } else if (adjpos == "i") | ||
656 | { | ||
657 | tnc._position = adjective::positioning::postnominal; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | output.push_back(tnc); | ||
662 | } | ||
663 | |||
664 | sqlite3_finalize(ppstmt); | ||
665 | |||
666 | for (auto& adjective : output) | ||
667 | { | ||
668 | query = "SELECT pronunciation FROM adjective_pronunciations WHERE adjective_id = ?"; | ||
669 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
670 | { | ||
671 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
672 | } | ||
673 | |||
674 | sqlite3_bind_int(ppstmt, 1, adjective._id); | ||
675 | |||
676 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
677 | { | ||
678 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
679 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
680 | |||
681 | adjective.pronunciations.push_back(phonemes); | ||
682 | } | ||
683 | |||
684 | sqlite3_finalize(ppstmt); | ||
685 | } | ||
686 | |||
687 | return output; | ||
688 | } | 111 | } |
689 | 112 | ||
690 | }; | 113 | }; |
diff --git a/lib/adjective.h b/lib/adjective.h index 3dcab9b..a6eb293 100644 --- a/lib/adjective.h +++ b/lib/adjective.h | |||
@@ -25,6 +25,7 @@ namespace verbly { | |||
25 | friend class adjective_query; | 25 | friend class adjective_query; |
26 | 26 | ||
27 | public: | 27 | public: |
28 | adjective(); | ||
28 | adjective(const data& _data, int _id); | 29 | adjective(const data& _data, int _id); |
29 | 30 | ||
30 | std::string base_form() const; | 31 | std::string base_form() const; |
@@ -45,99 +46,6 @@ namespace verbly { | |||
45 | noun_query attributes() const; | 46 | noun_query attributes() const; |
46 | }; | 47 | }; |
47 | 48 | ||
48 | class adjective_query { | ||
49 | public: | ||
50 | adjective_query(const data& _data); | ||
51 | |||
52 | adjective_query& limit(int _limit); | ||
53 | adjective_query& random(bool _random); | ||
54 | adjective_query& except(const adjective& _word); | ||
55 | adjective_query& rhymes_with(const word& _word); | ||
56 | adjective_query& has_pronunciation(bool _has_prn); | ||
57 | |||
58 | adjective_query& requires_comparative_form(bool req); | ||
59 | adjective_query& requires_superlative_form(bool req); | ||
60 | adjective_query& position(adjective::positioning pos); | ||
61 | |||
62 | adjective_query& is_variant(bool _is_variant); | ||
63 | adjective_query& variant_of(const noun& _noun); | ||
64 | adjective_query& not_variant_of(const noun& _noun); | ||
65 | |||
66 | adjective_query& has_antonyms(bool _is_antonymic); | ||
67 | adjective_query& antonym_of(const adjective& _adj); | ||
68 | adjective_query& not_antonym_of(const adjective& _adj); | ||
69 | |||
70 | adjective_query& has_synonyms(bool _is_synonymic); | ||
71 | adjective_query& synonym_of(const adjective& _adj); | ||
72 | adjective_query& not_synonym_of(const adjective& _adj); | ||
73 | |||
74 | adjective_query& is_generalization(bool _is_generalization); | ||
75 | adjective_query& generalization_of(const adjective& _adj); | ||
76 | adjective_query& not_generalization_of(const adjective& _adj); | ||
77 | |||
78 | adjective_query& is_specification(bool _is_specification); | ||
79 | adjective_query& specification_of(const adjective& _adj); | ||
80 | adjective_query& not_specification_of(const adjective& _adj); | ||
81 | |||
82 | adjective_query& is_pertainymic(bool _is_pertainymic); | ||
83 | adjective_query& pertainym_of(const noun& _noun); | ||
84 | |||
85 | adjective_query& is_mannernymic(bool _is_mannernymic); | ||
86 | adjective_query& anti_mannernym_of(const adverb& _adv); | ||
87 | |||
88 | adjective_query& derived_from(const word& _w); | ||
89 | adjective_query& not_derived_from(const word& _w); | ||
90 | |||
91 | std::list<adjective> run() const; | ||
92 | |||
93 | const static int unlimited = -1; | ||
94 | |||
95 | protected: | ||
96 | const data& _data; | ||
97 | int _limit = unlimited; | ||
98 | bool _random = false; | ||
99 | std::list<std::string> _rhymes; | ||
100 | std::list<adjective> _except; | ||
101 | bool _has_prn = false; | ||
102 | |||
103 | bool _requires_comparative_form = false; | ||
104 | bool _requires_superlative_form = false; | ||
105 | adjective::positioning _position = adjective::positioning::undefined; | ||
106 | |||
107 | bool _is_variant = false; | ||
108 | std::list<noun> _variant_of; | ||
109 | std::list<noun> _not_variant_of; | ||
110 | |||
111 | bool _is_antonymic = false; | ||
112 | std::list<adjective> _antonym_of; | ||
113 | std::list<adjective> _not_antonym_of; | ||
114 | |||
115 | bool _is_synonymic = false; | ||
116 | std::list<adjective> _synonym_of; | ||
117 | std::list<adjective> _not_synonym_of; | ||
118 | |||
119 | bool _is_generalization = false; | ||
120 | std::list<adjective> _generalization_of; | ||
121 | std::list<adjective> _not_generalization_of; | ||
122 | |||
123 | bool _is_specification = false; | ||
124 | std::list<adjective> _specification_of; | ||
125 | std::list<adjective> _not_specification_of; | ||
126 | |||
127 | bool _is_pertainymic = false; | ||
128 | std::list<noun> _pertainym_of; | ||
129 | |||
130 | bool _is_mannernymic = false; | ||
131 | std::list<adverb> _anti_mannernym_of; | ||
132 | |||
133 | std::list<adjective> _derived_from_adjective; | ||
134 | std::list<adjective> _not_derived_from_adjective; | ||
135 | std::list<adverb> _derived_from_adverb; | ||
136 | std::list<adverb> _not_derived_from_adverb; | ||
137 | std::list<noun> _derived_from_noun; | ||
138 | std::list<noun> _not_derived_from_noun; | ||
139 | }; | ||
140 | |||
141 | }; | 49 | }; |
142 | 50 | ||
143 | #endif /* end of include guard: ADJECTIVE_H_87B3FB75 */ | 51 | #endif /* end of include guard: ADJECTIVE_H_87B3FB75 */ |
diff --git a/lib/adjective_query.cpp b/lib/adjective_query.cpp new file mode 100644 index 0000000..ec100e3 --- /dev/null +++ b/lib/adjective_query.cpp | |||
@@ -0,0 +1,819 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | adjective_query::adjective_query(const data& _data) : _data(_data) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | adjective_query& adjective_query::limit(int _limit) | ||
11 | { | ||
12 | if ((_limit > 0) || (_limit == unlimited)) | ||
13 | { | ||
14 | this->_limit = _limit; | ||
15 | } | ||
16 | |||
17 | return *this; | ||
18 | } | ||
19 | |||
20 | adjective_query& adjective_query::random() | ||
21 | { | ||
22 | this->_random = true; | ||
23 | |||
24 | return *this; | ||
25 | } | ||
26 | |||
27 | adjective_query& adjective_query::except(const adjective& _word) | ||
28 | { | ||
29 | _except.push_back(_word); | ||
30 | |||
31 | return *this; | ||
32 | } | ||
33 | |||
34 | adjective_query& adjective_query::rhymes_with(const word& _word) | ||
35 | { | ||
36 | for (auto rhyme : _word.rhyme_phonemes()) | ||
37 | { | ||
38 | _rhymes.push_back(rhyme); | ||
39 | } | ||
40 | |||
41 | if (dynamic_cast<const adjective*>(&_word) != nullptr) | ||
42 | { | ||
43 | _except.push_back(dynamic_cast<const adjective&>(_word)); | ||
44 | } | ||
45 | |||
46 | return *this; | ||
47 | } | ||
48 | |||
49 | adjective_query& adjective_query::has_pronunciation() | ||
50 | { | ||
51 | this->_has_prn = true; | ||
52 | |||
53 | return *this; | ||
54 | } | ||
55 | |||
56 | adjective_query& adjective_query::is_variant() | ||
57 | { | ||
58 | this->_is_variant = true; | ||
59 | |||
60 | return *this; | ||
61 | } | ||
62 | |||
63 | adjective_query& adjective_query::variant_of(filter<noun> _f) | ||
64 | { | ||
65 | _f.clean(); | ||
66 | _variant_of = _f; | ||
67 | |||
68 | return *this; | ||
69 | } | ||
70 | |||
71 | adjective_query& adjective_query::has_antonyms() | ||
72 | { | ||
73 | this->_is_antonymic = true; | ||
74 | |||
75 | return *this; | ||
76 | } | ||
77 | |||
78 | adjective_query& adjective_query::antonym_of(filter<adjective> _f) | ||
79 | { | ||
80 | _f.clean(); | ||
81 | _antonym_of = _f; | ||
82 | |||
83 | return *this; | ||
84 | } | ||
85 | |||
86 | adjective_query& adjective_query::has_synonyms() | ||
87 | { | ||
88 | this->_is_synonymic = true; | ||
89 | |||
90 | return *this; | ||
91 | } | ||
92 | |||
93 | adjective_query& adjective_query::synonym_of(filter<adjective> _f) | ||
94 | { | ||
95 | _f.clean(); | ||
96 | _synonym_of = _f; | ||
97 | |||
98 | return *this; | ||
99 | } | ||
100 | |||
101 | adjective_query& adjective_query::is_generalization() | ||
102 | { | ||
103 | this->_is_generalization = true; | ||
104 | |||
105 | return *this; | ||
106 | } | ||
107 | |||
108 | adjective_query& adjective_query::generalization_of(filter<adjective> _f) | ||
109 | { | ||
110 | _f.clean(); | ||
111 | _generalization_of = _f; | ||
112 | |||
113 | return *this; | ||
114 | } | ||
115 | |||
116 | adjective_query& adjective_query::is_specification() | ||
117 | { | ||
118 | this->_is_specification = true; | ||
119 | |||
120 | return *this; | ||
121 | } | ||
122 | |||
123 | adjective_query& adjective_query::specification_of(filter<adjective> _f) | ||
124 | { | ||
125 | _f.clean(); | ||
126 | _specification_of = _f; | ||
127 | |||
128 | return *this; | ||
129 | } | ||
130 | |||
131 | adjective_query& adjective_query::is_pertainymic() | ||
132 | { | ||
133 | this->_is_pertainymic = true; | ||
134 | |||
135 | return *this; | ||
136 | } | ||
137 | |||
138 | adjective_query& adjective_query::pertainym_of(filter<noun> _f) | ||
139 | { | ||
140 | _f.clean(); | ||
141 | _pertainym_of = _f; | ||
142 | |||
143 | return *this; | ||
144 | } | ||
145 | |||
146 | adjective_query& adjective_query::is_mannernymic() | ||
147 | { | ||
148 | this->_is_mannernymic = true; | ||
149 | |||
150 | return *this; | ||
151 | } | ||
152 | |||
153 | adjective_query& adjective_query::anti_mannernym_of(filter<adverb> _f) | ||
154 | { | ||
155 | _f.clean(); | ||
156 | _anti_mannernym_of = _f; | ||
157 | |||
158 | return *this; | ||
159 | } | ||
160 | /* | ||
161 | adjective_query& adjective_query::derived_from(const word& _w) | ||
162 | { | ||
163 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
164 | { | ||
165 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
166 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
167 | { | ||
168 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
169 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
170 | { | ||
171 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
172 | } | ||
173 | |||
174 | return *this; | ||
175 | } | ||
176 | |||
177 | adjective_query& adjective_query::not_derived_from(const word& _w) | ||
178 | { | ||
179 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
180 | { | ||
181 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
182 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
183 | { | ||
184 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
185 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
186 | { | ||
187 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
188 | } | ||
189 | |||
190 | return *this; | ||
191 | } | ||
192 | */ | ||
193 | std::list<adjective> adjective_query::run() const | ||
194 | { | ||
195 | std::stringstream construct; | ||
196 | construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; | ||
197 | std::list<std::string> conditions; | ||
198 | |||
199 | if (_has_prn) | ||
200 | { | ||
201 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM adjective_pronunciations)"); | ||
202 | } | ||
203 | |||
204 | if (!_rhymes.empty()) | ||
205 | { | ||
206 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
207 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
208 | conditions.push_back(cond); | ||
209 | } | ||
210 | |||
211 | for (auto except : _except) | ||
212 | { | ||
213 | conditions.push_back("adjective_id != @EXCID"); | ||
214 | } | ||
215 | |||
216 | if (_requires_comparative_form) | ||
217 | { | ||
218 | conditions.push_back("comparative IS NOT NULL"); | ||
219 | } | ||
220 | |||
221 | if (_requires_superlative_form) | ||
222 | { | ||
223 | conditions.push_back("superlative IS NOT NULL"); | ||
224 | } | ||
225 | |||
226 | switch (_position) | ||
227 | { | ||
228 | case adjective::positioning::predicate: conditions.push_back("position = 'p'"); break; | ||
229 | case adjective::positioning::attributive: conditions.push_back("position = 'a'"); break; | ||
230 | case adjective::positioning::postnominal: conditions.push_back("position = 'i'"); break; | ||
231 | case adjective::positioning::undefined: break; | ||
232 | } | ||
233 | |||
234 | if (_is_variant) | ||
235 | { | ||
236 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)"); | ||
237 | } | ||
238 | |||
239 | if (!_variant_of.empty()) | ||
240 | { | ||
241 | std::stringstream cond; | ||
242 | if (_variant_of.get_notlogic()) | ||
243 | { | ||
244 | cond << "adjective_id NOT IN"; | ||
245 | } else { | ||
246 | cond << "adjective_id IN"; | ||
247 | } | ||
248 | |||
249 | cond << "(SELECT adjective_id FROM variation WHERE "; | ||
250 | |||
251 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
252 | switch (f.get_type()) | ||
253 | { | ||
254 | case filter<noun>::type::singleton: | ||
255 | { | ||
256 | if (notlogic == f.get_notlogic()) | ||
257 | { | ||
258 | return "noun_id = @ATTRID"; | ||
259 | } else { | ||
260 | return "noun_id != @ATTRID"; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | case filter<noun>::type::group: | ||
265 | { | ||
266 | bool truelogic = notlogic != f.get_notlogic(); | ||
267 | |||
268 | std::list<std::string> clauses; | ||
269 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
270 | return recur(f2, truelogic); | ||
271 | }); | ||
272 | |||
273 | if (truelogic == f.get_orlogic()) | ||
274 | { | ||
275 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
276 | } else { | ||
277 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | }; | ||
282 | |||
283 | cond << recur(_variant_of, _variant_of.get_notlogic()); | ||
284 | cond << ")"; | ||
285 | conditions.push_back(cond.str()); | ||
286 | } | ||
287 | |||
288 | if (_is_antonymic) | ||
289 | { | ||
290 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); | ||
291 | } | ||
292 | |||
293 | if (!_antonym_of.empty()) | ||
294 | { | ||
295 | std::stringstream cond; | ||
296 | if (_antonym_of.get_notlogic()) | ||
297 | { | ||
298 | cond << "adjective_id NOT IN"; | ||
299 | } else { | ||
300 | cond << "adjective_id IN"; | ||
301 | } | ||
302 | |||
303 | cond << "(SELECT adjective_2_id FROM adjective_antonymy WHERE "; | ||
304 | |||
305 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
306 | switch (f.get_type()) | ||
307 | { | ||
308 | case filter<adjective>::type::singleton: | ||
309 | { | ||
310 | if (notlogic == f.get_notlogic()) | ||
311 | { | ||
312 | return "adjective_1_id = @ANTID"; | ||
313 | } else { | ||
314 | return "adjective_1_id != @ANTID"; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | case filter<adjective>::type::group: | ||
319 | { | ||
320 | bool truelogic = notlogic != f.get_notlogic(); | ||
321 | |||
322 | std::list<std::string> clauses; | ||
323 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
324 | return recur(f2, truelogic); | ||
325 | }); | ||
326 | |||
327 | if (truelogic == f.get_orlogic()) | ||
328 | { | ||
329 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
330 | } else { | ||
331 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | }; | ||
336 | |||
337 | cond << recur(_antonym_of, _antonym_of.get_notlogic()); | ||
338 | cond << ")"; | ||
339 | conditions.push_back(cond.str()); | ||
340 | } | ||
341 | |||
342 | if (_is_synonymic) | ||
343 | { | ||
344 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); | ||
345 | } | ||
346 | |||
347 | if (!_synonym_of.empty()) | ||
348 | { | ||
349 | std::stringstream cond; | ||
350 | if (_synonym_of.get_notlogic()) | ||
351 | { | ||
352 | cond << "adjective_id NOT IN"; | ||
353 | } else { | ||
354 | cond << "adjective_id IN"; | ||
355 | } | ||
356 | |||
357 | cond << "(SELECT adjective_2_id FROM adjective_synonymy WHERE "; | ||
358 | |||
359 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
360 | switch (f.get_type()) | ||
361 | { | ||
362 | case filter<adjective>::type::singleton: | ||
363 | { | ||
364 | if (notlogic == f.get_notlogic()) | ||
365 | { | ||
366 | return "adjective_1_id = @SYNID"; | ||
367 | } else { | ||
368 | return "adjective_1_id != @SYNID"; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | case filter<adjective>::type::group: | ||
373 | { | ||
374 | bool truelogic = notlogic != f.get_notlogic(); | ||
375 | |||
376 | std::list<std::string> clauses; | ||
377 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
378 | return recur(f2, truelogic); | ||
379 | }); | ||
380 | |||
381 | if (truelogic == f.get_orlogic()) | ||
382 | { | ||
383 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
384 | } else { | ||
385 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
386 | } | ||
387 | } | ||
388 | } | ||
389 | }; | ||
390 | |||
391 | cond << recur(_synonym_of, _synonym_of.get_notlogic()); | ||
392 | cond << ")"; | ||
393 | conditions.push_back(cond.str()); | ||
394 | } | ||
395 | |||
396 | if (_is_generalization) | ||
397 | { | ||
398 | conditions.push_back("adjective_id IN (SELECT general_id FROM specification)"); | ||
399 | } | ||
400 | |||
401 | if (!_generalization_of.empty()) | ||
402 | { | ||
403 | std::stringstream cond; | ||
404 | if (_generalization_of.get_notlogic()) | ||
405 | { | ||
406 | cond << "adjective_id NOT IN"; | ||
407 | } else { | ||
408 | cond << "adjective_id IN"; | ||
409 | } | ||
410 | |||
411 | cond << "(SELECT general_id FROM specification WHERE "; | ||
412 | |||
413 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
414 | switch (f.get_type()) | ||
415 | { | ||
416 | case filter<adjective>::type::singleton: | ||
417 | { | ||
418 | if (notlogic == f.get_notlogic()) | ||
419 | { | ||
420 | return "specific_id = @SPECID"; | ||
421 | } else { | ||
422 | return "specific_id != @SPECID"; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | case filter<adjective>::type::group: | ||
427 | { | ||
428 | bool truelogic = notlogic != f.get_notlogic(); | ||
429 | |||
430 | std::list<std::string> clauses; | ||
431 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
432 | return recur(f2, truelogic); | ||
433 | }); | ||
434 | |||
435 | if (truelogic == f.get_orlogic()) | ||
436 | { | ||
437 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
438 | } else { | ||
439 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
440 | } | ||
441 | } | ||
442 | } | ||
443 | }; | ||
444 | |||
445 | cond << recur(_generalization_of, _generalization_of.get_notlogic()); | ||
446 | cond << ")"; | ||
447 | conditions.push_back(cond.str()); | ||
448 | } | ||
449 | |||
450 | if (_is_specification) | ||
451 | { | ||
452 | conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)"); | ||
453 | } | ||
454 | |||
455 | if (!_specification_of.empty()) | ||
456 | { | ||
457 | std::stringstream cond; | ||
458 | if (_specification_of.get_notlogic()) | ||
459 | { | ||
460 | cond << "adjective_id NOT IN"; | ||
461 | } else { | ||
462 | cond << "adjective_id IN"; | ||
463 | } | ||
464 | |||
465 | cond << "(SELECT specific_id FROM specification WHERE "; | ||
466 | |||
467 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
468 | switch (f.get_type()) | ||
469 | { | ||
470 | case filter<adjective>::type::singleton: | ||
471 | { | ||
472 | if (notlogic == f.get_notlogic()) | ||
473 | { | ||
474 | return "general_id = @GENID"; | ||
475 | } else { | ||
476 | return "general_id != @GENID"; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | case filter<adjective>::type::group: | ||
481 | { | ||
482 | bool truelogic = notlogic != f.get_notlogic(); | ||
483 | |||
484 | std::list<std::string> clauses; | ||
485 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
486 | return recur(f2, truelogic); | ||
487 | }); | ||
488 | |||
489 | if (truelogic == f.get_orlogic()) | ||
490 | { | ||
491 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
492 | } else { | ||
493 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | }; | ||
498 | |||
499 | cond << recur(_specification_of, _specification_of.get_notlogic()); | ||
500 | cond << ")"; | ||
501 | conditions.push_back(cond.str()); | ||
502 | } | ||
503 | |||
504 | if (_is_pertainymic) | ||
505 | { | ||
506 | conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)"); | ||
507 | } | ||
508 | |||
509 | if (!_pertainym_of.empty()) | ||
510 | { | ||
511 | std::stringstream cond; | ||
512 | if (_pertainym_of.get_notlogic()) | ||
513 | { | ||
514 | cond << "adjective_id NOT IN"; | ||
515 | } else { | ||
516 | cond << "adjective_id IN"; | ||
517 | } | ||
518 | |||
519 | cond << "(SELECT pertainym_id FROM pertainymy WHERE "; | ||
520 | |||
521 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
522 | switch (f.get_type()) | ||
523 | { | ||
524 | case filter<noun>::type::singleton: | ||
525 | { | ||
526 | if (notlogic == f.get_notlogic()) | ||
527 | { | ||
528 | return "noun_id = @APERID"; | ||
529 | } else { | ||
530 | return "noun_id != @APERID"; | ||
531 | } | ||
532 | } | ||
533 | |||
534 | case filter<noun>::type::group: | ||
535 | { | ||
536 | bool truelogic = notlogic != f.get_notlogic(); | ||
537 | |||
538 | std::list<std::string> clauses; | ||
539 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
540 | return recur(f2, truelogic); | ||
541 | }); | ||
542 | |||
543 | if (truelogic == f.get_orlogic()) | ||
544 | { | ||
545 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
546 | } else { | ||
547 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
548 | } | ||
549 | } | ||
550 | } | ||
551 | }; | ||
552 | |||
553 | cond << recur(_pertainym_of, _pertainym_of.get_notlogic()); | ||
554 | cond << ")"; | ||
555 | conditions.push_back(cond.str()); | ||
556 | } | ||
557 | |||
558 | if (_is_mannernymic) | ||
559 | { | ||
560 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)"); | ||
561 | } | ||
562 | |||
563 | if (!_anti_mannernym_of.empty()) | ||
564 | { | ||
565 | std::stringstream cond; | ||
566 | if (_anti_mannernym_of.get_notlogic()) | ||
567 | { | ||
568 | cond << "adjective_id NOT IN"; | ||
569 | } else { | ||
570 | cond << "adjective_id IN"; | ||
571 | } | ||
572 | |||
573 | cond << "(SELECT adjective_id FROM mannernymy WHERE "; | ||
574 | |||
575 | std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string { | ||
576 | switch (f.get_type()) | ||
577 | { | ||
578 | case filter<adverb>::type::singleton: | ||
579 | { | ||
580 | if (notlogic == f.get_notlogic()) | ||
581 | { | ||
582 | return "mannernym_id = @MANID"; | ||
583 | } else { | ||
584 | return "mannernym_id != @MANID"; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | case filter<adverb>::type::group: | ||
589 | { | ||
590 | bool truelogic = notlogic != f.get_notlogic(); | ||
591 | |||
592 | std::list<std::string> clauses; | ||
593 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) { | ||
594 | return recur(f2, truelogic); | ||
595 | }); | ||
596 | |||
597 | if (truelogic == f.get_orlogic()) | ||
598 | { | ||
599 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
600 | } else { | ||
601 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
602 | } | ||
603 | } | ||
604 | } | ||
605 | }; | ||
606 | |||
607 | cond << recur(_anti_mannernym_of, _anti_mannernym_of.get_notlogic()); | ||
608 | cond << ")"; | ||
609 | conditions.push_back(cond.str()); | ||
610 | } | ||
611 | /* | ||
612 | if (!_derived_from_adjective.empty()) | ||
613 | { | ||
614 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_2_id = @DERADJ"); | ||
615 | std::string cond = "adjective_id IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
616 | conditions.push_back(cond); | ||
617 | } | ||
618 | |||
619 | if (!_not_derived_from_adjective.empty()) | ||
620 | { | ||
621 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_2_id = @NDERADJ"); | ||
622 | std::string cond = "adjective_id NOT IN (SELECT adjective_1_id FROM adjective_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
623 | conditions.push_back(cond); | ||
624 | } | ||
625 | |||
626 | if (!_derived_from_adverb.empty()) | ||
627 | { | ||
628 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); | ||
629 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
630 | conditions.push_back(cond); | ||
631 | } | ||
632 | |||
633 | if (!_not_derived_from_adverb.empty()) | ||
634 | { | ||
635 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); | ||
636 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
637 | conditions.push_back(cond); | ||
638 | } | ||
639 | |||
640 | if (!_derived_from_noun.empty()) | ||
641 | { | ||
642 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN"); | ||
643 | std::string cond = "adjective_id IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
644 | conditions.push_back(cond); | ||
645 | } | ||
646 | |||
647 | if (!_not_derived_from_noun.empty()) | ||
648 | { | ||
649 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); | ||
650 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
651 | conditions.push_back(cond); | ||
652 | }*/ | ||
653 | |||
654 | if (!conditions.empty()) | ||
655 | { | ||
656 | construct << " WHERE "; | ||
657 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
658 | } | ||
659 | |||
660 | if (_random) | ||
661 | { | ||
662 | construct << " ORDER BY RANDOM()"; | ||
663 | } | ||
664 | |||
665 | if (_limit != unlimited) | ||
666 | { | ||
667 | construct << " LIMIT " << _limit; | ||
668 | } | ||
669 | |||
670 | sqlite3_stmt* ppstmt; | ||
671 | std::string query = construct.str(); | ||
672 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
673 | { | ||
674 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
675 | } | ||
676 | |||
677 | if (!_rhymes.empty()) | ||
678 | { | ||
679 | int i = 0; | ||
680 | for (auto rhyme : _rhymes) | ||
681 | { | ||
682 | std::string rhymer = "%" + rhyme; | ||
683 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
684 | |||
685 | i++; | ||
686 | } | ||
687 | } | ||
688 | |||
689 | for (auto except : _except) | ||
690 | { | ||
691 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
692 | } | ||
693 | |||
694 | for (auto attribute : _variant_of.inorder_flatten()) | ||
695 | { | ||
696 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ATTRID"), attribute._id); | ||
697 | } | ||
698 | |||
699 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
700 | { | ||
701 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
702 | } | ||
703 | |||
704 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
705 | { | ||
706 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
707 | } | ||
708 | |||
709 | for (auto specific : _generalization_of.inorder_flatten()) | ||
710 | { | ||
711 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SPECID"), specific._id); | ||
712 | } | ||
713 | |||
714 | for (auto general : _specification_of.inorder_flatten()) | ||
715 | { | ||
716 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GENID"), general._id); | ||
717 | } | ||
718 | |||
719 | for (auto n : _pertainym_of.inorder_flatten()) | ||
720 | { | ||
721 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@APERID"), n._id); | ||
722 | } | ||
723 | |||
724 | for (auto mannernym : _anti_mannernym_of.inorder_flatten()) | ||
725 | { | ||
726 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MANID"), mannernym._id); | ||
727 | } | ||
728 | /* | ||
729 | for (auto adj : _derived_from_adjective) | ||
730 | { | ||
731 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
732 | } | ||
733 | |||
734 | for (auto adj : _not_derived_from_adjective) | ||
735 | { | ||
736 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
737 | } | ||
738 | |||
739 | for (auto adv : _derived_from_adverb) | ||
740 | { | ||
741 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
742 | } | ||
743 | |||
744 | for (auto adv : _not_derived_from_adverb) | ||
745 | { | ||
746 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
747 | } | ||
748 | |||
749 | for (auto n : _derived_from_noun) | ||
750 | { | ||
751 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
752 | } | ||
753 | |||
754 | for (auto n : _not_derived_from_noun) | ||
755 | { | ||
756 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
757 | } | ||
758 | */ | ||
759 | std::list<adjective> output; | ||
760 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
761 | { | ||
762 | adjective tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
763 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
764 | |||
765 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
766 | { | ||
767 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
768 | } | ||
769 | |||
770 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
771 | { | ||
772 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
773 | } | ||
774 | |||
775 | if (sqlite3_column_type(ppstmt, 4) != SQLITE_NULL) | ||
776 | { | ||
777 | std::string adjpos(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
778 | if (adjpos == "p") | ||
779 | { | ||
780 | tnc._position = adjective::positioning::predicate; | ||
781 | } else if (adjpos == "a") | ||
782 | { | ||
783 | tnc._position = adjective::positioning::attributive; | ||
784 | } else if (adjpos == "i") | ||
785 | { | ||
786 | tnc._position = adjective::positioning::postnominal; | ||
787 | } | ||
788 | } | ||
789 | |||
790 | output.push_back(tnc); | ||
791 | } | ||
792 | |||
793 | sqlite3_finalize(ppstmt); | ||
794 | |||
795 | for (auto& adjective : output) | ||
796 | { | ||
797 | query = "SELECT pronunciation FROM adjective_pronunciations WHERE adjective_id = ?"; | ||
798 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
799 | { | ||
800 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
801 | } | ||
802 | |||
803 | sqlite3_bind_int(ppstmt, 1, adjective._id); | ||
804 | |||
805 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
806 | { | ||
807 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
808 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
809 | |||
810 | adjective.pronunciations.push_back(phonemes); | ||
811 | } | ||
812 | |||
813 | sqlite3_finalize(ppstmt); | ||
814 | } | ||
815 | |||
816 | return output; | ||
817 | } | ||
818 | |||
819 | }; | ||
diff --git a/lib/adjective_query.h b/lib/adjective_query.h new file mode 100644 index 0000000..e7755cb --- /dev/null +++ b/lib/adjective_query.h | |||
@@ -0,0 +1,91 @@ | |||
1 | #ifndef ADJECTIVE_QUERY_H_05E590FD | ||
2 | #define ADJECTIVE_QUERY_H_05E590FD | ||
3 | |||
4 | namespace verbly { | ||
5 | |||
6 | class adjective_query { | ||
7 | public: | ||
8 | adjective_query(const data& _data); | ||
9 | |||
10 | adjective_query& limit(int _limit); | ||
11 | adjective_query& random(); | ||
12 | adjective_query& except(const adjective& _word); | ||
13 | adjective_query& rhymes_with(const word& _word); | ||
14 | adjective_query& has_pronunciation(); | ||
15 | |||
16 | adjective_query& requires_comparative_form(); | ||
17 | adjective_query& requires_superlative_form(); | ||
18 | adjective_query& position(adjective::positioning pos); | ||
19 | |||
20 | adjective_query& is_variant(); | ||
21 | adjective_query& variant_of(filter<noun> _f); | ||
22 | |||
23 | adjective_query& has_antonyms(); | ||
24 | adjective_query& antonym_of(filter<adjective> _f); | ||
25 | |||
26 | adjective_query& has_synonyms(); | ||
27 | adjective_query& synonym_of(filter<adjective> _f); | ||
28 | |||
29 | adjective_query& is_generalization(); | ||
30 | adjective_query& generalization_of(filter<adjective> _f); | ||
31 | |||
32 | adjective_query& is_specification(); | ||
33 | adjective_query& specification_of(filter<adjective> _f); | ||
34 | |||
35 | adjective_query& is_pertainymic(); | ||
36 | adjective_query& pertainym_of(filter<noun> _f); | ||
37 | |||
38 | adjective_query& is_mannernymic(); | ||
39 | adjective_query& anti_mannernym_of(filter<adverb> _f); | ||
40 | |||
41 | /* adjective_query& derived_from(const word& _w); | ||
42 | adjective_query& not_derived_from(const word& _w);*/ | ||
43 | |||
44 | std::list<adjective> run() const; | ||
45 | |||
46 | const static int unlimited = -1; | ||
47 | |||
48 | protected: | ||
49 | const data& _data; | ||
50 | int _limit = unlimited; | ||
51 | bool _random = false; | ||
52 | std::list<std::string> _rhymes; | ||
53 | std::list<adjective> _except; | ||
54 | bool _has_prn = false; | ||
55 | |||
56 | bool _requires_comparative_form = false; | ||
57 | bool _requires_superlative_form = false; | ||
58 | adjective::positioning _position = adjective::positioning::undefined; | ||
59 | |||
60 | bool _is_variant = false; | ||
61 | filter<noun> _variant_of; | ||
62 | |||
63 | bool _is_antonymic = false; | ||
64 | filter<adjective> _antonym_of; | ||
65 | |||
66 | bool _is_synonymic = false; | ||
67 | filter<adjective> _synonym_of; | ||
68 | |||
69 | bool _is_generalization = false; | ||
70 | filter<adjective> _generalization_of; | ||
71 | |||
72 | bool _is_specification = false; | ||
73 | filter<adjective> _specification_of; | ||
74 | |||
75 | bool _is_pertainymic = false; | ||
76 | filter<noun> _pertainym_of; | ||
77 | |||
78 | bool _is_mannernymic = false; | ||
79 | filter<adverb> _anti_mannernym_of; | ||
80 | |||
81 | /* std::list<adjective> _derived_from_adjective; | ||
82 | std::list<adjective> _not_derived_from_adjective; | ||
83 | std::list<adverb> _derived_from_adverb; | ||
84 | std::list<adverb> _not_derived_from_adverb; | ||
85 | std::list<noun> _derived_from_noun; | ||
86 | std::list<noun> _not_derived_from_noun;*/ | ||
87 | }; | ||
88 | |||
89 | }; | ||
90 | |||
91 | #endif /* end of include guard: ADJECTIVE_QUERY_H_05E590FD */ | ||
diff --git a/lib/adverb.cpp b/lib/adverb.cpp index 8fcddad..442574e 100644 --- a/lib/adverb.cpp +++ b/lib/adverb.cpp | |||
@@ -2,6 +2,11 @@ | |||
2 | 2 | ||
3 | namespace verbly { | 3 | namespace verbly { |
4 | 4 | ||
5 | adverb::adverb() | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
5 | adverb::adverb(const data& _data, int _id) : word(_data, _id) | 10 | adverb::adverb(const data& _data, int _id) : word(_data, _id) |
6 | { | 11 | { |
7 | 12 | ||
@@ -9,460 +14,58 @@ namespace verbly { | |||
9 | 14 | ||
10 | std::string adverb::base_form() const | 15 | std::string adverb::base_form() const |
11 | { | 16 | { |
17 | assert(_valid == true); | ||
18 | |||
12 | return _base_form; | 19 | return _base_form; |
13 | } | 20 | } |
14 | 21 | ||
15 | std::string adverb::comparative_form() const | 22 | std::string adverb::comparative_form() const |
16 | { | 23 | { |
24 | assert(_valid == true); | ||
25 | |||
17 | return _comparative_form; | 26 | return _comparative_form; |
18 | } | 27 | } |
19 | 28 | ||
20 | std::string adverb::superlative_form() const | 29 | std::string adverb::superlative_form() const |
21 | { | 30 | { |
31 | assert(_valid == true); | ||
32 | |||
22 | return _superlative_form; | 33 | return _superlative_form; |
23 | } | 34 | } |
24 | 35 | ||
25 | bool adverb::has_comparative_form() const | 36 | bool adverb::has_comparative_form() const |
26 | { | 37 | { |
38 | assert(_valid == true); | ||
39 | |||
27 | return !_comparative_form.empty(); | 40 | return !_comparative_form.empty(); |
28 | } | 41 | } |
29 | 42 | ||
30 | bool adverb::has_superlative_form() const | 43 | bool adverb::has_superlative_form() const |
31 | { | 44 | { |
45 | assert(_valid == true); | ||
46 | |||
32 | return !_superlative_form.empty(); | 47 | return !_superlative_form.empty(); |
33 | } | 48 | } |
34 | 49 | ||
35 | adverb_query adverb::antonyms() const | 50 | adverb_query adverb::antonyms() const |
36 | { | 51 | { |
37 | return _data.adverbs().antonym_of(*this); | 52 | assert(_valid == true); |
38 | } | ||
39 | |||
40 | adverb_query adverb::synonyms() const | ||
41 | { | ||
42 | return _data.adverbs().synonym_of(*this); | ||
43 | } | ||
44 | |||
45 | adjective_query adverb::anti_mannernyms() const | ||
46 | { | ||
47 | return _data.adjectives().anti_mannernym_of(*this); | ||
48 | } | ||
49 | |||
50 | adverb_query::adverb_query(const data& _data) : _data(_data) | ||
51 | { | ||
52 | |||
53 | } | ||
54 | |||
55 | adverb_query& adverb_query::limit(int _limit) | ||
56 | { | ||
57 | if ((_limit > 0) || (_limit == unlimited)) | ||
58 | { | ||
59 | this->_limit = _limit; | ||
60 | } | ||
61 | |||
62 | return *this; | ||
63 | } | ||
64 | |||
65 | adverb_query& adverb_query::random(bool _random) | ||
66 | { | ||
67 | this->_random = _random; | ||
68 | |||
69 | return *this; | ||
70 | } | ||
71 | |||
72 | adverb_query& adverb_query::except(const adverb& _word) | ||
73 | { | ||
74 | _except.push_back(_word); | ||
75 | 53 | ||
76 | return *this; | 54 | return _data->adverbs().antonym_of(*this); |
77 | } | 55 | } |
78 | 56 | ||
79 | adverb_query& adverb_query::rhymes_with(const word& _word) | 57 | adverb_query adverb::synonyms() const |
80 | { | ||
81 | for (auto rhyme : _word.rhyme_phonemes()) | ||
82 | { | ||
83 | _rhymes.push_back(rhyme); | ||
84 | } | ||
85 | |||
86 | if (dynamic_cast<const adverb*>(&_word) != nullptr) | ||
87 | { | ||
88 | _except.push_back(dynamic_cast<const adverb&>(_word)); | ||
89 | } | ||
90 | |||
91 | return *this; | ||
92 | } | ||
93 | |||
94 | adverb_query& adverb_query::has_pronunciation(bool _has_prn) | ||
95 | { | ||
96 | this->_has_prn = _has_prn; | ||
97 | |||
98 | return *this; | ||
99 | } | ||
100 | |||
101 | adverb_query& adverb_query::requires_comparative_form(bool _arg) | ||
102 | { | ||
103 | _requires_comparative_form = _arg; | ||
104 | |||
105 | return *this; | ||
106 | } | ||
107 | |||
108 | adverb_query& adverb_query::requires_superlative_form(bool _arg) | ||
109 | { | ||
110 | _requires_superlative_form = _arg; | ||
111 | |||
112 | return *this; | ||
113 | } | ||
114 | |||
115 | adverb_query& adverb_query::has_antonyms(bool _arg) | ||
116 | { | ||
117 | _has_antonyms = _arg; | ||
118 | |||
119 | return *this; | ||
120 | } | ||
121 | |||
122 | adverb_query& adverb_query::antonym_of(const adverb& _adv) | ||
123 | { | ||
124 | _antonym_of.push_back(_adv); | ||
125 | |||
126 | return *this; | ||
127 | } | ||
128 | |||
129 | adverb_query& adverb_query::not_antonym_of(const adverb& _adv) | ||
130 | { | ||
131 | _not_antonym_of.push_back(_adv); | ||
132 | |||
133 | return *this; | ||
134 | } | ||
135 | |||
136 | adverb_query& adverb_query::has_synonyms(bool _arg) | ||
137 | { | ||
138 | _has_synonyms = _arg; | ||
139 | |||
140 | return *this; | ||
141 | } | ||
142 | |||
143 | adverb_query& adverb_query::synonym_of(const adverb& _adv) | ||
144 | { | ||
145 | _synonym_of.push_back(_adv); | ||
146 | |||
147 | return *this; | ||
148 | } | ||
149 | |||
150 | adverb_query& adverb_query::not_synonym_of(const adverb& _adv) | ||
151 | { | ||
152 | _not_synonym_of.push_back(_adv); | ||
153 | |||
154 | return *this; | ||
155 | } | ||
156 | |||
157 | adverb_query& adverb_query::is_mannernymic(bool _arg) | ||
158 | { | ||
159 | _is_mannernymic = _arg; | ||
160 | |||
161 | return *this; | ||
162 | } | ||
163 | |||
164 | adverb_query& adverb_query::mannernym_of(const adjective& _adj) | ||
165 | { | ||
166 | _mannernym_of.push_back(_adj); | ||
167 | |||
168 | return *this; | ||
169 | } | ||
170 | |||
171 | adverb_query& adverb_query::derived_from(const word& _w) | ||
172 | { | ||
173 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
174 | { | ||
175 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
176 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
177 | { | ||
178 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
179 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
180 | { | ||
181 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
182 | } | ||
183 | |||
184 | return *this; | ||
185 | } | ||
186 | |||
187 | adverb_query& adverb_query::not_derived_from(const word& _w) | ||
188 | { | 58 | { |
189 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 59 | assert(_valid == true); |
190 | { | ||
191 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
192 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
193 | { | ||
194 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
195 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
196 | { | ||
197 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
198 | } | ||
199 | 60 | ||
200 | return *this; | 61 | return _data->adverbs().synonym_of(*this); |
201 | } | 62 | } |
202 | 63 | ||
203 | std::list<adverb> adverb_query::run() const | 64 | adjective_query adverb::anti_mannernyms() const |
204 | { | 65 | { |
205 | std::stringstream construct; | 66 | assert(_valid == true); |
206 | construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; | ||
207 | std::list<std::string> conditions; | ||
208 | |||
209 | if (_has_prn) | ||
210 | { | ||
211 | conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)"); | ||
212 | } | ||
213 | |||
214 | if (!_rhymes.empty()) | ||
215 | { | ||
216 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
217 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
218 | conditions.push_back(cond); | ||
219 | } | ||
220 | |||
221 | for (auto except : _except) | ||
222 | { | ||
223 | conditions.push_back("adverb_id != @EXCID"); | ||
224 | } | ||
225 | |||
226 | if (_requires_comparative_form) | ||
227 | { | ||
228 | conditions.push_back("comparative IS NOT NULL"); | ||
229 | } | ||
230 | |||
231 | if (_requires_superlative_form) | ||
232 | { | ||
233 | conditions.push_back("superlative IS NOT NULL"); | ||
234 | } | ||
235 | |||
236 | if (_has_antonyms) | ||
237 | { | ||
238 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)"); | ||
239 | } | ||
240 | |||
241 | if (!_antonym_of.empty()) | ||
242 | { | ||
243 | std::list<std::string> clauses(_antonym_of.size(), "adverb_1_id = @ANTID"); | ||
244 | std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
245 | conditions.push_back(cond); | ||
246 | } | ||
247 | |||
248 | if (!_not_antonym_of.empty()) | ||
249 | { | ||
250 | std::list<std::string> clauses(_not_antonym_of.size(), "adverb_1_id = @NANTID"); | ||
251 | std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
252 | conditions.push_back(cond); | ||
253 | } | ||
254 | |||
255 | if (_has_synonyms) | ||
256 | { | ||
257 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)"); | ||
258 | } | ||
259 | 67 | ||
260 | if (!_synonym_of.empty()) | 68 | return _data->adjectives().anti_mannernym_of(*this); |
261 | { | ||
262 | std::list<std::string> clauses(_synonym_of.size(), "adverb_1_id = @SYNID"); | ||
263 | std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
264 | conditions.push_back(cond); | ||
265 | } | ||
266 | |||
267 | if (!_not_synonym_of.empty()) | ||
268 | { | ||
269 | std::list<std::string> clauses(_not_synonym_of.size(), "adverb_1_id = @NSYNID"); | ||
270 | std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
271 | conditions.push_back(cond); | ||
272 | } | ||
273 | |||
274 | if (_is_mannernymic) | ||
275 | { | ||
276 | conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)"); | ||
277 | } | ||
278 | |||
279 | if (!_mannernym_of.empty()) | ||
280 | { | ||
281 | std::list<std::string> clauses(_mannernym_of.size(), "adjective_id = @AMANID"); | ||
282 | std::string cond = "adverb_id IN (SELECT mannernym_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
283 | conditions.push_back(cond); | ||
284 | } | ||
285 | |||
286 | if (!_derived_from_adjective.empty()) | ||
287 | { | ||
288 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); | ||
289 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
290 | conditions.push_back(cond); | ||
291 | } | ||
292 | |||
293 | if (!_not_derived_from_adjective.empty()) | ||
294 | { | ||
295 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); | ||
296 | std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
297 | conditions.push_back(cond); | ||
298 | } | ||
299 | |||
300 | if (!_derived_from_adverb.empty()) | ||
301 | { | ||
302 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_2_id = @DERADV"); | ||
303 | std::string cond = "adverb_id IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
304 | conditions.push_back(cond); | ||
305 | } | ||
306 | |||
307 | if (!_not_derived_from_adverb.empty()) | ||
308 | { | ||
309 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_2_id = @NDERADV"); | ||
310 | std::string cond = "adverb_id NOT IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
311 | conditions.push_back(cond); | ||
312 | } | ||
313 | |||
314 | if (!_derived_from_noun.empty()) | ||
315 | { | ||
316 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN"); | ||
317 | std::string cond = "adverb_id IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
318 | conditions.push_back(cond); | ||
319 | } | ||
320 | |||
321 | if (!_not_derived_from_noun.empty()) | ||
322 | { | ||
323 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); | ||
324 | std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
325 | conditions.push_back(cond); | ||
326 | } | ||
327 | |||
328 | if (!conditions.empty()) | ||
329 | { | ||
330 | construct << " WHERE "; | ||
331 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
332 | } | ||
333 | |||
334 | if (_random) | ||
335 | { | ||
336 | construct << " ORDER BY RANDOM()"; | ||
337 | } | ||
338 | |||
339 | if (_limit != unlimited) | ||
340 | { | ||
341 | construct << " LIMIT " << _limit; | ||
342 | } | ||
343 | |||
344 | sqlite3_stmt* ppstmt; | ||
345 | std::string query = construct.str(); | ||
346 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
347 | { | ||
348 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
349 | } | ||
350 | |||
351 | if (!_rhymes.empty()) | ||
352 | { | ||
353 | int i = 0; | ||
354 | for (auto rhyme : _rhymes) | ||
355 | { | ||
356 | std::string rhymer = "%" + rhyme; | ||
357 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
358 | |||
359 | i++; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | for (auto except : _except) | ||
364 | { | ||
365 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
366 | } | ||
367 | |||
368 | for (auto antonym : _antonym_of) | ||
369 | { | ||
370 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
371 | } | ||
372 | |||
373 | for (auto antonym : _not_antonym_of) | ||
374 | { | ||
375 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
376 | } | ||
377 | |||
378 | for (auto synonym : _synonym_of) | ||
379 | { | ||
380 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
381 | } | ||
382 | |||
383 | for (auto synonym : _not_synonym_of) | ||
384 | { | ||
385 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
386 | } | ||
387 | |||
388 | for (auto adj : _mannernym_of) | ||
389 | { | ||
390 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@AMANID"), adj._id); | ||
391 | } | ||
392 | |||
393 | for (auto adj : _derived_from_adjective) | ||
394 | { | ||
395 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
396 | } | ||
397 | |||
398 | for (auto adj : _not_derived_from_adjective) | ||
399 | { | ||
400 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
401 | } | ||
402 | |||
403 | for (auto adv : _derived_from_adverb) | ||
404 | { | ||
405 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
406 | } | ||
407 | |||
408 | for (auto adv : _not_derived_from_adverb) | ||
409 | { | ||
410 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
411 | } | ||
412 | |||
413 | for (auto n : _derived_from_noun) | ||
414 | { | ||
415 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
416 | } | ||
417 | |||
418 | for (auto n : _not_derived_from_noun) | ||
419 | { | ||
420 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
421 | } | ||
422 | |||
423 | std::list<adverb> output; | ||
424 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
425 | { | ||
426 | adverb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
427 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
428 | |||
429 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
430 | { | ||
431 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
432 | } | ||
433 | |||
434 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
435 | { | ||
436 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
437 | } | ||
438 | |||
439 | output.push_back(tnc); | ||
440 | } | ||
441 | |||
442 | sqlite3_finalize(ppstmt); | ||
443 | |||
444 | for (auto& adverb : output) | ||
445 | { | ||
446 | query = "SELECT pronunciation FROM adverb_pronunciations WHERE adverb_id = ?"; | ||
447 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
448 | { | ||
449 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
450 | } | ||
451 | |||
452 | sqlite3_bind_int(ppstmt, 1, adverb._id); | ||
453 | |||
454 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
455 | { | ||
456 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
457 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
458 | |||
459 | adverb.pronunciations.push_back(phonemes); | ||
460 | } | ||
461 | |||
462 | sqlite3_finalize(ppstmt); | ||
463 | } | ||
464 | |||
465 | return output; | ||
466 | } | 69 | } |
467 | 70 | ||
468 | }; | 71 | }; |
diff --git a/lib/adverb.h b/lib/adverb.h index 65e3c5c..56d4e28 100644 --- a/lib/adverb.h +++ b/lib/adverb.h | |||
@@ -12,6 +12,7 @@ namespace verbly { | |||
12 | friend class adverb_query; | 12 | friend class adverb_query; |
13 | 13 | ||
14 | public: | 14 | public: |
15 | adverb(); | ||
15 | adverb(const data& _data, int _id); | 16 | adverb(const data& _data, int _id); |
16 | 17 | ||
17 | std::string base_form() const; | 18 | std::string base_form() const; |
@@ -29,67 +30,6 @@ namespace verbly { | |||
29 | adverb_query& not_derived_from(const word& _w); | 30 | adverb_query& not_derived_from(const word& _w); |
30 | }; | 31 | }; |
31 | 32 | ||
32 | class adverb_query { | ||
33 | public: | ||
34 | adverb_query(const data& _data); | ||
35 | |||
36 | adverb_query& limit(int _limit); | ||
37 | adverb_query& random(bool _random); | ||
38 | adverb_query& except(const adverb& _word); | ||
39 | adverb_query& rhymes_with(const word& _word); | ||
40 | adverb_query& has_pronunciation(bool _has_prn); | ||
41 | |||
42 | adverb_query& requires_comparative_form(bool _arg); | ||
43 | adverb_query& requires_superlative_form(bool _arg); | ||
44 | |||
45 | adverb_query& has_antonyms(bool _arg); | ||
46 | adverb_query& antonym_of(const adverb& _adv); | ||
47 | adverb_query& not_antonym_of(const adverb& _adv); | ||
48 | |||
49 | adverb_query& has_synonyms(bool _arg); | ||
50 | adverb_query& synonym_of(const adverb& _adv); | ||
51 | adverb_query& not_synonym_of(const adverb& _adv); | ||
52 | |||
53 | adverb_query& is_mannernymic(bool _arg); | ||
54 | adverb_query& mannernym_of(const adjective& _adj); | ||
55 | |||
56 | adverb_query& derived_from(const word& _w); | ||
57 | adverb_query& not_derived_from(const word& _w); | ||
58 | |||
59 | std::list<adverb> run() const; | ||
60 | |||
61 | const static int unlimited = -1; | ||
62 | |||
63 | private: | ||
64 | const data& _data; | ||
65 | int _limit = unlimited; | ||
66 | bool _random = false; | ||
67 | std::list<std::string> _rhymes; | ||
68 | std::list<adverb> _except; | ||
69 | bool _has_prn = false; | ||
70 | |||
71 | bool _requires_comparative_form = false; | ||
72 | bool _requires_superlative_form = false; | ||
73 | |||
74 | bool _has_antonyms = false; | ||
75 | std::list<adverb> _antonym_of; | ||
76 | std::list<adverb> _not_antonym_of; | ||
77 | |||
78 | bool _has_synonyms = false; | ||
79 | std::list<adverb> _synonym_of; | ||
80 | std::list<adverb> _not_synonym_of; | ||
81 | |||
82 | bool _is_mannernymic = false; | ||
83 | std::list<adjective> _mannernym_of; | ||
84 | |||
85 | std::list<adjective> _derived_from_adjective; | ||
86 | std::list<adjective> _not_derived_from_adjective; | ||
87 | std::list<adverb> _derived_from_adverb; | ||
88 | std::list<adverb> _not_derived_from_adverb; | ||
89 | std::list<noun> _derived_from_noun; | ||
90 | std::list<noun> _not_derived_from_noun; | ||
91 | }; | ||
92 | |||
93 | }; | 33 | }; |
94 | 34 | ||
95 | #endif /* end of include guard: ADVERB_H_86F8302F */ | 35 | #endif /* end of include guard: ADVERB_H_86F8302F */ |
diff --git a/lib/adverb_query.cpp b/lib/adverb_query.cpp new file mode 100644 index 0000000..639f16f --- /dev/null +++ b/lib/adverb_query.cpp | |||
@@ -0,0 +1,514 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | adverb_query::adverb_query(const data& _data) : _data(_data) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | adverb_query& adverb_query::limit(int _limit) | ||
11 | { | ||
12 | if ((_limit > 0) || (_limit == unlimited)) | ||
13 | { | ||
14 | this->_limit = _limit; | ||
15 | } | ||
16 | |||
17 | return *this; | ||
18 | } | ||
19 | |||
20 | adverb_query& adverb_query::random() | ||
21 | { | ||
22 | this->_random = true; | ||
23 | |||
24 | return *this; | ||
25 | } | ||
26 | |||
27 | adverb_query& adverb_query::except(const adverb& _word) | ||
28 | { | ||
29 | _except.push_back(_word); | ||
30 | |||
31 | return *this; | ||
32 | } | ||
33 | |||
34 | adverb_query& adverb_query::rhymes_with(const word& _word) | ||
35 | { | ||
36 | for (auto rhyme : _word.rhyme_phonemes()) | ||
37 | { | ||
38 | _rhymes.push_back(rhyme); | ||
39 | } | ||
40 | |||
41 | if (dynamic_cast<const adverb*>(&_word) != nullptr) | ||
42 | { | ||
43 | _except.push_back(dynamic_cast<const adverb&>(_word)); | ||
44 | } | ||
45 | |||
46 | return *this; | ||
47 | } | ||
48 | |||
49 | adverb_query& adverb_query::has_pronunciation() | ||
50 | { | ||
51 | this->_has_prn = true; | ||
52 | |||
53 | return *this; | ||
54 | } | ||
55 | |||
56 | adverb_query& adverb_query::requires_comparative_form() | ||
57 | { | ||
58 | _requires_comparative_form = true; | ||
59 | |||
60 | return *this; | ||
61 | } | ||
62 | |||
63 | adverb_query& adverb_query::requires_superlative_form() | ||
64 | { | ||
65 | _requires_superlative_form = true; | ||
66 | |||
67 | return *this; | ||
68 | } | ||
69 | |||
70 | adverb_query& adverb_query::has_antonyms() | ||
71 | { | ||
72 | _has_antonyms = true; | ||
73 | |||
74 | return *this; | ||
75 | } | ||
76 | |||
77 | adverb_query& adverb_query::antonym_of(filter<adverb> _f) | ||
78 | { | ||
79 | _f.clean(); | ||
80 | _antonym_of = _f; | ||
81 | |||
82 | return *this; | ||
83 | } | ||
84 | |||
85 | adverb_query& adverb_query::has_synonyms() | ||
86 | { | ||
87 | _has_synonyms = true; | ||
88 | |||
89 | return *this; | ||
90 | } | ||
91 | |||
92 | adverb_query& adverb_query::synonym_of(filter<adverb> _f) | ||
93 | { | ||
94 | _f.clean(); | ||
95 | _synonym_of = _f; | ||
96 | |||
97 | return *this; | ||
98 | } | ||
99 | |||
100 | adverb_query& adverb_query::is_mannernymic() | ||
101 | { | ||
102 | _is_mannernymic = true; | ||
103 | |||
104 | return *this; | ||
105 | } | ||
106 | |||
107 | adverb_query& adverb_query::mannernym_of(filter<adjective> _f) | ||
108 | { | ||
109 | _f.clean(); | ||
110 | _mannernym_of = _f; | ||
111 | |||
112 | return *this; | ||
113 | } | ||
114 | /* | ||
115 | adverb_query& adverb_query::derived_from(const word& _w) | ||
116 | { | ||
117 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
118 | { | ||
119 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
120 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
121 | { | ||
122 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
123 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
124 | { | ||
125 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
126 | } | ||
127 | |||
128 | return *this; | ||
129 | } | ||
130 | |||
131 | adverb_query& adverb_query::not_derived_from(const word& _w) | ||
132 | { | ||
133 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
134 | { | ||
135 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
136 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
137 | { | ||
138 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
139 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
140 | { | ||
141 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
142 | } | ||
143 | |||
144 | return *this; | ||
145 | } | ||
146 | */ | ||
147 | std::list<adverb> adverb_query::run() const | ||
148 | { | ||
149 | std::stringstream construct; | ||
150 | construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; | ||
151 | std::list<std::string> conditions; | ||
152 | |||
153 | if (_has_prn) | ||
154 | { | ||
155 | conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)"); | ||
156 | } | ||
157 | |||
158 | if (!_rhymes.empty()) | ||
159 | { | ||
160 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
161 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
162 | conditions.push_back(cond); | ||
163 | } | ||
164 | |||
165 | for (auto except : _except) | ||
166 | { | ||
167 | conditions.push_back("adverb_id != @EXCID"); | ||
168 | } | ||
169 | |||
170 | if (_requires_comparative_form) | ||
171 | { | ||
172 | conditions.push_back("comparative IS NOT NULL"); | ||
173 | } | ||
174 | |||
175 | if (_requires_superlative_form) | ||
176 | { | ||
177 | conditions.push_back("superlative IS NOT NULL"); | ||
178 | } | ||
179 | |||
180 | if (_has_antonyms) | ||
181 | { | ||
182 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)"); | ||
183 | } | ||
184 | |||
185 | if (!_antonym_of.empty()) | ||
186 | { | ||
187 | std::stringstream cond; | ||
188 | if (_antonym_of.get_notlogic()) | ||
189 | { | ||
190 | cond << "adverb_id NOT IN"; | ||
191 | } else { | ||
192 | cond << "adverb_id IN"; | ||
193 | } | ||
194 | |||
195 | cond << "(SELECT adverb_2_id FROM adverb_antonymy WHERE "; | ||
196 | |||
197 | std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string { | ||
198 | switch (f.get_type()) | ||
199 | { | ||
200 | case filter<adverb>::type::singleton: | ||
201 | { | ||
202 | if (notlogic == f.get_notlogic()) | ||
203 | { | ||
204 | return "adverb_1_id = @ANTID"; | ||
205 | } else { | ||
206 | return "adverb_1_id != @ANTID"; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | case filter<adverb>::type::group: | ||
211 | { | ||
212 | bool truelogic = notlogic != f.get_notlogic(); | ||
213 | |||
214 | std::list<std::string> clauses; | ||
215 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) { | ||
216 | return recur(f2, truelogic); | ||
217 | }); | ||
218 | |||
219 | if (truelogic == f.get_orlogic()) | ||
220 | { | ||
221 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
222 | } else { | ||
223 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
224 | } | ||
225 | } | ||
226 | } | ||
227 | }; | ||
228 | |||
229 | cond << recur(_antonym_of, _antonym_of.get_notlogic()); | ||
230 | cond << ")"; | ||
231 | conditions.push_back(cond.str()); | ||
232 | } | ||
233 | |||
234 | if (_has_synonyms) | ||
235 | { | ||
236 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)"); | ||
237 | } | ||
238 | |||
239 | if (!_synonym_of.empty()) | ||
240 | { | ||
241 | std::stringstream cond; | ||
242 | if (_antonym_of.get_notlogic()) | ||
243 | { | ||
244 | cond << "adverb_id NOT IN"; | ||
245 | } else { | ||
246 | cond << "adverb_id IN"; | ||
247 | } | ||
248 | |||
249 | cond << "(SELECT adverb_2_id FROM adverb_synonymy WHERE "; | ||
250 | |||
251 | std::function<std::string (filter<adverb>, bool)> recur = [&] (filter<adverb> f, bool notlogic) -> std::string { | ||
252 | switch (f.get_type()) | ||
253 | { | ||
254 | case filter<adverb>::type::singleton: | ||
255 | { | ||
256 | if (notlogic == f.get_notlogic()) | ||
257 | { | ||
258 | return "adverb_1_id = @SYNID"; | ||
259 | } else { | ||
260 | return "adverb_1_id != @SYNID"; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | case filter<adverb>::type::group: | ||
265 | { | ||
266 | bool truelogic = notlogic != f.get_notlogic(); | ||
267 | |||
268 | std::list<std::string> clauses; | ||
269 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adverb> f2) { | ||
270 | return recur(f2, truelogic); | ||
271 | }); | ||
272 | |||
273 | if (truelogic == f.get_orlogic()) | ||
274 | { | ||
275 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
276 | } else { | ||
277 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | }; | ||
282 | |||
283 | cond << recur(_synonym_of, _synonym_of.get_notlogic()); | ||
284 | cond << ")"; | ||
285 | conditions.push_back(cond.str()); | ||
286 | } | ||
287 | |||
288 | if (_is_mannernymic) | ||
289 | { | ||
290 | conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)"); | ||
291 | } | ||
292 | |||
293 | if (!_mannernym_of.empty()) | ||
294 | { | ||
295 | std::stringstream cond; | ||
296 | if (_antonym_of.get_notlogic()) | ||
297 | { | ||
298 | cond << "adverb_id NOT IN"; | ||
299 | } else { | ||
300 | cond << "adverb_id IN"; | ||
301 | } | ||
302 | |||
303 | cond << "(SELECT mannernym_id FROM mannernymy WHERE "; | ||
304 | |||
305 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
306 | switch (f.get_type()) | ||
307 | { | ||
308 | case filter<adjective>::type::singleton: | ||
309 | { | ||
310 | if (notlogic == f.get_notlogic()) | ||
311 | { | ||
312 | return "adjective_id = @AMANID"; | ||
313 | } else { | ||
314 | return "adjective_id != @AMANID"; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | case filter<adjective>::type::group: | ||
319 | { | ||
320 | bool truelogic = notlogic != f.get_notlogic(); | ||
321 | |||
322 | std::list<std::string> clauses; | ||
323 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
324 | return recur(f2, truelogic); | ||
325 | }); | ||
326 | |||
327 | if (truelogic == f.get_orlogic()) | ||
328 | { | ||
329 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
330 | } else { | ||
331 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | }; | ||
336 | |||
337 | cond << recur(_mannernym_of, _mannernym_of.get_notlogic()); | ||
338 | cond << ")"; | ||
339 | conditions.push_back(cond.str()); | ||
340 | } | ||
341 | |||
342 | /* if (!_derived_from_adjective.empty()) | ||
343 | { | ||
344 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); | ||
345 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
346 | conditions.push_back(cond); | ||
347 | } | ||
348 | |||
349 | if (!_not_derived_from_adjective.empty()) | ||
350 | { | ||
351 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); | ||
352 | std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
353 | conditions.push_back(cond); | ||
354 | } | ||
355 | |||
356 | if (!_derived_from_adverb.empty()) | ||
357 | { | ||
358 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_2_id = @DERADV"); | ||
359 | std::string cond = "adverb_id IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
360 | conditions.push_back(cond); | ||
361 | } | ||
362 | |||
363 | if (!_not_derived_from_adverb.empty()) | ||
364 | { | ||
365 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_2_id = @NDERADV"); | ||
366 | std::string cond = "adverb_id NOT IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
367 | conditions.push_back(cond); | ||
368 | } | ||
369 | |||
370 | if (!_derived_from_noun.empty()) | ||
371 | { | ||
372 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN"); | ||
373 | std::string cond = "adverb_id IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
374 | conditions.push_back(cond); | ||
375 | } | ||
376 | |||
377 | if (!_not_derived_from_noun.empty()) | ||
378 | { | ||
379 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN"); | ||
380 | std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
381 | conditions.push_back(cond); | ||
382 | }*/ | ||
383 | |||
384 | if (!conditions.empty()) | ||
385 | { | ||
386 | construct << " WHERE "; | ||
387 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
388 | } | ||
389 | |||
390 | if (_random) | ||
391 | { | ||
392 | construct << " ORDER BY RANDOM()"; | ||
393 | } | ||
394 | |||
395 | if (_limit != unlimited) | ||
396 | { | ||
397 | construct << " LIMIT " << _limit; | ||
398 | } | ||
399 | |||
400 | sqlite3_stmt* ppstmt; | ||
401 | std::string query = construct.str(); | ||
402 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
403 | { | ||
404 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
405 | } | ||
406 | |||
407 | if (!_rhymes.empty()) | ||
408 | { | ||
409 | int i = 0; | ||
410 | for (auto rhyme : _rhymes) | ||
411 | { | ||
412 | std::string rhymer = "%" + rhyme; | ||
413 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
414 | |||
415 | i++; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | for (auto except : _except) | ||
420 | { | ||
421 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
422 | } | ||
423 | |||
424 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
425 | { | ||
426 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
427 | } | ||
428 | |||
429 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
430 | { | ||
431 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
432 | } | ||
433 | |||
434 | for (auto adj : _mannernym_of.inorder_flatten()) | ||
435 | { | ||
436 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@AMANID"), adj._id); | ||
437 | } | ||
438 | /* | ||
439 | for (auto adj : _derived_from_adjective) | ||
440 | { | ||
441 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
442 | } | ||
443 | |||
444 | for (auto adj : _not_derived_from_adjective) | ||
445 | { | ||
446 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
447 | } | ||
448 | |||
449 | for (auto adv : _derived_from_adverb) | ||
450 | { | ||
451 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
452 | } | ||
453 | |||
454 | for (auto adv : _not_derived_from_adverb) | ||
455 | { | ||
456 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
457 | } | ||
458 | |||
459 | for (auto n : _derived_from_noun) | ||
460 | { | ||
461 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
462 | } | ||
463 | |||
464 | for (auto n : _not_derived_from_noun) | ||
465 | { | ||
466 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
467 | }*/ | ||
468 | |||
469 | std::list<adverb> output; | ||
470 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
471 | { | ||
472 | adverb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
473 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
474 | |||
475 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
476 | { | ||
477 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
478 | } | ||
479 | |||
480 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
481 | { | ||
482 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
483 | } | ||
484 | |||
485 | output.push_back(tnc); | ||
486 | } | ||
487 | |||
488 | sqlite3_finalize(ppstmt); | ||
489 | |||
490 | for (auto& adverb : output) | ||
491 | { | ||
492 | query = "SELECT pronunciation FROM adverb_pronunciations WHERE adverb_id = ?"; | ||
493 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
494 | { | ||
495 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
496 | } | ||
497 | |||
498 | sqlite3_bind_int(ppstmt, 1, adverb._id); | ||
499 | |||
500 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
501 | { | ||
502 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
503 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
504 | |||
505 | adverb.pronunciations.push_back(phonemes); | ||
506 | } | ||
507 | |||
508 | sqlite3_finalize(ppstmt); | ||
509 | } | ||
510 | |||
511 | return output; | ||
512 | } | ||
513 | |||
514 | }; | ||
diff --git a/lib/adverb_query.h b/lib/adverb_query.h new file mode 100644 index 0000000..20f9ce5 --- /dev/null +++ b/lib/adverb_query.h | |||
@@ -0,0 +1,65 @@ | |||
1 | #ifndef ADVERB_QUERY_H_CA13CCDD | ||
2 | #define ADVERB_QUERY_H_CA13CCDD | ||
3 | |||
4 | namespace verbly { | ||
5 | |||
6 | class adverb_query { | ||
7 | public: | ||
8 | adverb_query(const data& _data); | ||
9 | |||
10 | adverb_query& limit(int _limit); | ||
11 | adverb_query& random(); | ||
12 | adverb_query& except(const adverb& _word); | ||
13 | adverb_query& rhymes_with(const word& _word); | ||
14 | adverb_query& has_pronunciation(); | ||
15 | |||
16 | adverb_query& requires_comparative_form(); | ||
17 | adverb_query& requires_superlative_form(); | ||
18 | |||
19 | adverb_query& has_antonyms(); | ||
20 | adverb_query& antonym_of(filter<adverb> _f); | ||
21 | |||
22 | adverb_query& has_synonyms(); | ||
23 | adverb_query& synonym_of(filter<adverb> _f); | ||
24 | |||
25 | adverb_query& is_mannernymic(); | ||
26 | adverb_query& mannernym_of(filter<adjective> _f); | ||
27 | |||
28 | /* adverb_query& derived_from(const word& _w); | ||
29 | adverb_query& not_derived_from(const word& _w);*/ | ||
30 | |||
31 | std::list<adverb> run() const; | ||
32 | |||
33 | const static int unlimited = -1; | ||
34 | |||
35 | private: | ||
36 | const data& _data; | ||
37 | int _limit = unlimited; | ||
38 | bool _random = false; | ||
39 | std::list<std::string> _rhymes; | ||
40 | std::list<adverb> _except; | ||
41 | bool _has_prn = false; | ||
42 | |||
43 | bool _requires_comparative_form = false; | ||
44 | bool _requires_superlative_form = false; | ||
45 | |||
46 | bool _has_antonyms = false; | ||
47 | filter<adverb> _antonym_of; | ||
48 | |||
49 | bool _has_synonyms = false; | ||
50 | filter<adverb> _synonym_of; | ||
51 | |||
52 | bool _is_mannernymic = false; | ||
53 | filter<adjective> _mannernym_of; | ||
54 | |||
55 | /* std::list<adjective> _derived_from_adjective; | ||
56 | std::list<adjective> _not_derived_from_adjective; | ||
57 | std::list<adverb> _derived_from_adverb; | ||
58 | std::list<adverb> _not_derived_from_adverb; | ||
59 | std::list<noun> _derived_from_noun; | ||
60 | std::list<noun> _not_derived_from_noun;*/ | ||
61 | }; | ||
62 | |||
63 | }; | ||
64 | |||
65 | #endif /* end of include guard: ADVERB_QUERY_H_CA13CCDD */ | ||
diff --git a/lib/c++14.h b/lib/c++14.h deleted file mode 100644 index b3efbe2..0000000 --- a/lib/c++14.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | #include <cstddef> | ||
2 | #include <memory> | ||
3 | #include <type_traits> | ||
4 | #include <utility> | ||
5 | |||
6 | namespace std { | ||
7 | template<class T> struct _Unique_if { | ||
8 | typedef unique_ptr<T> _Single_object; | ||
9 | }; | ||
10 | |||
11 | template<class T> struct _Unique_if<T[]> { | ||
12 | typedef unique_ptr<T[]> _Unknown_bound; | ||
13 | }; | ||
14 | |||
15 | template<class T, size_t N> struct _Unique_if<T[N]> { | ||
16 | typedef void _Known_bound; | ||
17 | }; | ||
18 | |||
19 | template<class T, class... Args> | ||
20 | typename _Unique_if<T>::_Single_object | ||
21 | make_unique(Args&&... args) { | ||
22 | return unique_ptr<T>(new T(std::forward<Args>(args)...)); | ||
23 | } | ||
24 | |||
25 | template<class T> | ||
26 | typename _Unique_if<T>::_Unknown_bound | ||
27 | make_unique(size_t n) { | ||
28 | typedef typename remove_extent<T>::type U; | ||
29 | return unique_ptr<T>(new U[n]()); | ||
30 | } | ||
31 | |||
32 | template<class T, class... Args> | ||
33 | typename _Unique_if<T>::_Known_bound | ||
34 | make_unique(Args&&...) = delete; | ||
35 | } | ||
diff --git a/lib/data.cpp b/lib/data.cpp index 57a8850..5a9397b 100644 --- a/lib/data.cpp +++ b/lib/data.cpp | |||
@@ -46,5 +46,15 @@ namespace verbly { | |||
46 | { | 46 | { |
47 | return noun_query(*this); | 47 | return noun_query(*this); |
48 | } | 48 | } |
49 | 49 | ||
50 | frame_query data::frames() const | ||
51 | { | ||
52 | return frame_query(*this); | ||
53 | } | ||
54 | |||
55 | preposition_query data::prepositions() const | ||
56 | { | ||
57 | return preposition_query(*this); | ||
58 | } | ||
59 | |||
50 | }; | 60 | }; |
diff --git a/lib/data.h b/lib/data.h index 37092d7..6c2d580 100644 --- a/lib/data.h +++ b/lib/data.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #define DATA_H_C4AEC3DD | 2 | #define DATA_H_C4AEC3DD |
3 | 3 | ||
4 | #include <sqlite3.h> | 4 | #include <sqlite3.h> |
5 | #include <stdexcept> | ||
6 | 5 | ||
7 | namespace verbly { | 6 | namespace verbly { |
8 | 7 | ||
@@ -12,10 +11,13 @@ namespace verbly { | |||
12 | class noun; | 11 | class noun; |
13 | class verb; | 12 | class verb; |
14 | class adverb; | 13 | class adverb; |
14 | class frame; | ||
15 | class adjective_query; | 15 | class adjective_query; |
16 | class adverb_query; | 16 | class adverb_query; |
17 | class noun_query; | 17 | class noun_query; |
18 | class verb_query; | 18 | class verb_query; |
19 | class frame_query; | ||
20 | class preposition_query; | ||
19 | 21 | ||
20 | class data { | 22 | class data { |
21 | private: | 23 | private: |
@@ -25,6 +27,8 @@ namespace verbly { | |||
25 | friend class noun_query; | 27 | friend class noun_query; |
26 | friend class verb_query; | 28 | friend class verb_query; |
27 | friend class adverb_query; | 29 | friend class adverb_query; |
30 | friend class frame_query; | ||
31 | friend class preposition_query; | ||
28 | 32 | ||
29 | public: | 33 | public: |
30 | data(std::string datafile); | 34 | data(std::string datafile); |
@@ -41,9 +45,302 @@ namespace verbly { | |||
41 | adjective_query adjectives() const; | 45 | adjective_query adjectives() const; |
42 | adverb_query adverbs() const; | 46 | adverb_query adverbs() const; |
43 | noun_query nouns() const; | 47 | noun_query nouns() const; |
48 | frame_query frames() const; | ||
49 | preposition_query prepositions() const; | ||
44 | 50 | ||
45 | }; | 51 | }; |
46 | 52 | ||
53 | template <class T> | ||
54 | class filter { | ||
55 | public: | ||
56 | enum class type { | ||
57 | singleton, | ||
58 | group | ||
59 | }; | ||
60 | |||
61 | typedef filter<T> value_type; | ||
62 | |||
63 | type get_type() const | ||
64 | { | ||
65 | return _type; | ||
66 | } | ||
67 | |||
68 | filter(const filter<T>& other) | ||
69 | { | ||
70 | _type = other._type; | ||
71 | _notlogic = other._notlogic; | ||
72 | |||
73 | switch (_type) | ||
74 | { | ||
75 | case type::singleton: | ||
76 | { | ||
77 | new(&_singleton.elem) T(other._singleton.elem); | ||
78 | |||
79 | break; | ||
80 | } | ||
81 | |||
82 | case type::group: | ||
83 | { | ||
84 | new(&_group.elems) std::list<filter<T>>(other._group.elems); | ||
85 | _group.orlogic = other._group.orlogic; | ||
86 | |||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | filter<T>& operator=(const filter<T>& other) | ||
93 | { | ||
94 | this->~filter(); | ||
95 | |||
96 | _type = other._type; | ||
97 | _notlogic = other._notlogic; | ||
98 | |||
99 | switch (_type) | ||
100 | { | ||
101 | case type::singleton: | ||
102 | { | ||
103 | new(&_singleton.elem) T(other._singleton.elem); | ||
104 | |||
105 | break; | ||
106 | } | ||
107 | |||
108 | case type::group: | ||
109 | { | ||
110 | new(&_group.elems) std::list<filter<T>>(other._group.elems); | ||
111 | _group.orlogic = other._group.orlogic; | ||
112 | |||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | return *this; | ||
118 | } | ||
119 | |||
120 | ~filter() | ||
121 | { | ||
122 | switch (_type) | ||
123 | { | ||
124 | case type::singleton: | ||
125 | { | ||
126 | _singleton.elem.~T(); | ||
127 | |||
128 | break; | ||
129 | } | ||
130 | |||
131 | case type::group: | ||
132 | { | ||
133 | using list_type = std::list<filter<T>>; | ||
134 | _group.elems.~list_type(); | ||
135 | |||
136 | break; | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | |||
141 | bool get_notlogic() const | ||
142 | { | ||
143 | return _notlogic; | ||
144 | } | ||
145 | |||
146 | void set_notlogic(bool _nl) | ||
147 | { | ||
148 | _notlogic = _nl; | ||
149 | } | ||
150 | |||
151 | std::list<T> inorder_flatten() const | ||
152 | { | ||
153 | std::list<T> result; | ||
154 | |||
155 | if (_type == type::singleton) | ||
156 | { | ||
157 | result.push_back(_singleton.elem); | ||
158 | } else if (_type == type::group) | ||
159 | { | ||
160 | for (auto elem : _group.elems) | ||
161 | { | ||
162 | auto l = elem.inorder_flatten(); | ||
163 | result.insert(std::end(result), std::begin(l), std::end(l)); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | return result; | ||
168 | } | ||
169 | |||
170 | std::set<T> uniq_flatten() const | ||
171 | { | ||
172 | std::set<T> result; | ||
173 | |||
174 | if (_type == type::singleton) | ||
175 | { | ||
176 | result.insert(_singleton.elem); | ||
177 | } else if (_type == type::group) | ||
178 | { | ||
179 | for (auto elem : _group.elems) | ||
180 | { | ||
181 | auto l = elem.uniq_flatten(); | ||
182 | result.insert(std::begin(l), std::end(l)); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | return result; | ||
187 | } | ||
188 | |||
189 | void clean() | ||
190 | { | ||
191 | if (_type == type::group) | ||
192 | { | ||
193 | std::list<typename std::list<filter<T>>::iterator> toremove; | ||
194 | for (auto it = _group.elems.begin(); it != _group.elems.end(); it++) | ||
195 | { | ||
196 | it->clean(); | ||
197 | |||
198 | if (it->get_type() == type::group) | ||
199 | { | ||
200 | if (it->_group.elems.size() == 0) | ||
201 | { | ||
202 | toremove.push_back(it); | ||
203 | } else if (it->_group.elems.size() == 1) | ||
204 | { | ||
205 | bool truelogic = it->_notlogic != it->_group.elems.front()._notlogic; | ||
206 | *it = it->_group.elems.front(); | ||
207 | it->_notlogic = truelogic; | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | |||
212 | for (auto rem : toremove) | ||
213 | { | ||
214 | _group.elems.erase(rem); | ||
215 | } | ||
216 | |||
217 | if (_group.elems.size() == 1) | ||
218 | { | ||
219 | bool truelogic = _notlogic != _group.elems.front()._notlogic; | ||
220 | *this = _group.elems.front(); | ||
221 | _notlogic = truelogic; | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | |||
226 | // Singleton | ||
227 | filter(T _elem, bool _notlogic = false) : _type(type::singleton) | ||
228 | { | ||
229 | new(&_singleton.elem) T(_elem); | ||
230 | this->_notlogic = _notlogic; | ||
231 | } | ||
232 | |||
233 | filter<T>& operator=(T _elem) | ||
234 | { | ||
235 | *this = filter<T>{_elem}; | ||
236 | |||
237 | return *this; | ||
238 | } | ||
239 | |||
240 | T get_elem() const | ||
241 | { | ||
242 | assert(_type == type::singleton); | ||
243 | |||
244 | return _singleton.elem; | ||
245 | } | ||
246 | |||
247 | void set_elem(T _elem) | ||
248 | { | ||
249 | assert(_type == type::singleton); | ||
250 | |||
251 | _singleton.elem = _elem; | ||
252 | } | ||
253 | |||
254 | // Group | ||
255 | typedef typename std::list<filter<T>>::iterator iterator; | ||
256 | |||
257 | filter() : _type(type::group) | ||
258 | { | ||
259 | new(&_group.elems) std::list<filter<T>>(); | ||
260 | _group.orlogic = false; | ||
261 | } | ||
262 | |||
263 | filter(std::initializer_list<filter<T>> _init) : _type(type::group) | ||
264 | { | ||
265 | new(&_group.elems) std::list<filter<T>>(_init); | ||
266 | _group.orlogic = false; | ||
267 | } | ||
268 | |||
269 | iterator begin() | ||
270 | { | ||
271 | assert(_type == type::group); | ||
272 | |||
273 | return _group.elems.begin(); | ||
274 | } | ||
275 | |||
276 | iterator end() | ||
277 | { | ||
278 | assert(_type == type::group); | ||
279 | |||
280 | return _group.elems.end(); | ||
281 | } | ||
282 | |||
283 | filter<T>& operator<<(filter<T> _elem) | ||
284 | { | ||
285 | assert(_type == type::group); | ||
286 | |||
287 | _group.elems.push_back(_elem); | ||
288 | |||
289 | return *this; | ||
290 | } | ||
291 | |||
292 | void push_back(filter<T> _elem) | ||
293 | { | ||
294 | assert(_type == type::group); | ||
295 | |||
296 | _group.elems.push_back(_elem); | ||
297 | } | ||
298 | |||
299 | bool get_orlogic() const | ||
300 | { | ||
301 | assert(_type == type::group); | ||
302 | |||
303 | return _group.orlogic; | ||
304 | } | ||
305 | |||
306 | void set_orlogic(bool _ol) | ||
307 | { | ||
308 | assert(_type == type::group); | ||
309 | |||
310 | _group.orlogic = _ol; | ||
311 | } | ||
312 | |||
313 | bool empty() const | ||
314 | { | ||
315 | if (_type == type::group) | ||
316 | { | ||
317 | return _group.elems.empty(); | ||
318 | } else { | ||
319 | return false; | ||
320 | } | ||
321 | } | ||
322 | |||
323 | int size() const | ||
324 | { | ||
325 | assert(_type == type::group); | ||
326 | |||
327 | return _group.elems.size(); | ||
328 | } | ||
329 | |||
330 | private: | ||
331 | type _type; | ||
332 | bool _notlogic = false; | ||
333 | union { | ||
334 | struct { | ||
335 | T elem; | ||
336 | } _singleton; | ||
337 | struct { | ||
338 | std::list<filter<T>> elems; | ||
339 | bool orlogic; | ||
340 | } _group; | ||
341 | }; | ||
342 | }; | ||
343 | |||
47 | }; | 344 | }; |
48 | 345 | ||
49 | #endif /* end of include guard: DATA_H_C4AEC3DD */ | 346 | #endif /* end of include guard: DATA_H_C4AEC3DD */ |
diff --git a/lib/frame.cpp b/lib/frame.cpp new file mode 100644 index 0000000..ccec81b --- /dev/null +++ b/lib/frame.cpp | |||
@@ -0,0 +1,320 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | frame::selrestr::type frame::selrestr::get_type() const | ||
6 | { | ||
7 | return _type; | ||
8 | } | ||
9 | |||
10 | frame::selrestr::selrestr(const selrestr& other) | ||
11 | { | ||
12 | _type = other._type; | ||
13 | |||
14 | switch (_type) | ||
15 | { | ||
16 | case frame::selrestr::type::singleton: | ||
17 | { | ||
18 | _singleton.pos = other._singleton.pos; | ||
19 | new(&_singleton.restriction) std::string(other._singleton.restriction); | ||
20 | |||
21 | break; | ||
22 | } | ||
23 | |||
24 | case frame::selrestr::type::group: | ||
25 | { | ||
26 | new(&_group.children) std::list<selrestr>(other._group.children); | ||
27 | _group.orlogic = other._group.orlogic; | ||
28 | |||
29 | break; | ||
30 | } | ||
31 | |||
32 | case frame::selrestr::type::empty: | ||
33 | { | ||
34 | // Nothing! | ||
35 | |||
36 | break; | ||
37 | } | ||
38 | } | ||
39 | } | ||
40 | |||
41 | frame::selrestr::~selrestr() | ||
42 | { | ||
43 | switch (_type) | ||
44 | { | ||
45 | case frame::selrestr::type::singleton: | ||
46 | { | ||
47 | using string_type = std::string; | ||
48 | _singleton.restriction.~string_type(); | ||
49 | |||
50 | break; | ||
51 | } | ||
52 | |||
53 | case frame::selrestr::type::group: | ||
54 | { | ||
55 | using list_type = std::list<selrestr>; | ||
56 | _group.children.~list_type(); | ||
57 | |||
58 | break; | ||
59 | } | ||
60 | |||
61 | case frame::selrestr::type::empty: | ||
62 | { | ||
63 | // Nothing! | ||
64 | |||
65 | break; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | frame::selrestr& frame::selrestr::operator=(const selrestr& other) | ||
71 | { | ||
72 | this->~selrestr(); | ||
73 | |||
74 | _type = other._type; | ||
75 | |||
76 | switch (_type) | ||
77 | { | ||
78 | case frame::selrestr::type::singleton: | ||
79 | { | ||
80 | _singleton.pos = other._singleton.pos; | ||
81 | new(&_singleton.restriction) std::string(other._singleton.restriction); | ||
82 | |||
83 | break; | ||
84 | } | ||
85 | |||
86 | case frame::selrestr::type::group: | ||
87 | { | ||
88 | new(&_group.children) std::list<selrestr>(other._group.children); | ||
89 | _group.orlogic = other._group.orlogic; | ||
90 | |||
91 | break; | ||
92 | } | ||
93 | |||
94 | case frame::selrestr::type::empty: | ||
95 | { | ||
96 | // Nothing! | ||
97 | |||
98 | break; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | return *this; | ||
103 | } | ||
104 | |||
105 | frame::selrestr::selrestr() : _type(frame::selrestr::type::empty) | ||
106 | { | ||
107 | |||
108 | } | ||
109 | |||
110 | frame::selrestr::selrestr(std::string restriction, bool pos) : _type(frame::selrestr::type::singleton) | ||
111 | { | ||
112 | new(&_singleton.restriction) std::string(restriction); | ||
113 | _singleton.pos = pos; | ||
114 | } | ||
115 | |||
116 | std::string frame::selrestr::get_restriction() const | ||
117 | { | ||
118 | assert(_type == frame::selrestr::type::singleton); | ||
119 | |||
120 | return _singleton.restriction; | ||
121 | } | ||
122 | |||
123 | bool frame::selrestr::get_pos() const | ||
124 | { | ||
125 | assert(_type == frame::selrestr::type::singleton); | ||
126 | |||
127 | return _singleton.pos; | ||
128 | } | ||
129 | |||
130 | frame::selrestr::selrestr(std::list<selrestr> children, bool orlogic) : _type(frame::selrestr::type::group) | ||
131 | { | ||
132 | new(&_group.children) std::list<selrestr>(children); | ||
133 | _group.orlogic = orlogic; | ||
134 | } | ||
135 | |||
136 | std::list<frame::selrestr> frame::selrestr::get_children() const | ||
137 | { | ||
138 | assert(_type == frame::selrestr::type::group); | ||
139 | |||
140 | return _group.children; | ||
141 | } | ||
142 | |||
143 | std::list<frame::selrestr>::const_iterator frame::selrestr::begin() const | ||
144 | { | ||
145 | assert(_type == frame::selrestr::type::group); | ||
146 | |||
147 | return _group.children.begin(); | ||
148 | } | ||
149 | |||
150 | std::list<frame::selrestr>::const_iterator frame::selrestr::end() const | ||
151 | { | ||
152 | assert(_type == frame::selrestr::type::group); | ||
153 | |||
154 | return _group.children.end(); | ||
155 | } | ||
156 | |||
157 | bool frame::selrestr::get_orlogic() const | ||
158 | { | ||
159 | assert(_type == frame::selrestr::type::group); | ||
160 | |||
161 | return _group.orlogic; | ||
162 | } | ||
163 | |||
164 | frame::part::type frame::part::get_type() const | ||
165 | { | ||
166 | return _type; | ||
167 | } | ||
168 | |||
169 | frame::part::part() | ||
170 | { | ||
171 | |||
172 | } | ||
173 | |||
174 | frame::part::part(const part& other) | ||
175 | { | ||
176 | _type = other._type; | ||
177 | |||
178 | switch (_type) | ||
179 | { | ||
180 | case frame::part::type::noun_phrase: | ||
181 | { | ||
182 | new(&_noun_phrase.role) std::string(other._noun_phrase.role); | ||
183 | new(&_noun_phrase.selrestrs) selrestr(other._noun_phrase.selrestrs); | ||
184 | new(&_noun_phrase.synrestrs) std::set<std::string>(other._noun_phrase.synrestrs); | ||
185 | |||
186 | break; | ||
187 | } | ||
188 | |||
189 | case frame::part::type::literal_preposition: | ||
190 | { | ||
191 | new(&_literal_preposition.choices) std::vector<std::string>(other._literal_preposition.choices); | ||
192 | |||
193 | break; | ||
194 | } | ||
195 | |||
196 | case frame::part::type::selection_preposition: | ||
197 | { | ||
198 | new(&_selection_preposition.preprestrs) std::vector<std::string>(other._selection_preposition.preprestrs); | ||
199 | |||
200 | break; | ||
201 | } | ||
202 | |||
203 | case frame::part::type::literal: | ||
204 | { | ||
205 | new(&_literal.lexval) std::string(other._literal.lexval); | ||
206 | |||
207 | break; | ||
208 | } | ||
209 | |||
210 | default: | ||
211 | { | ||
212 | // Nothing! | ||
213 | |||
214 | break; | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | frame::part::~part() | ||
220 | { | ||
221 | switch (_type) | ||
222 | { | ||
223 | case frame::part::type::noun_phrase: | ||
224 | { | ||
225 | using string_type = std::string; | ||
226 | using set_type = std::set<std::string>; | ||
227 | |||
228 | _noun_phrase.role.~string_type(); | ||
229 | _noun_phrase.selrestrs.~selrestr(); | ||
230 | _noun_phrase.synrestrs.~set_type(); | ||
231 | |||
232 | break; | ||
233 | } | ||
234 | |||
235 | case frame::part::type::literal_preposition: | ||
236 | { | ||
237 | using vector_type = std::vector<std::string>; | ||
238 | _literal_preposition.choices.~vector_type(); | ||
239 | |||
240 | break; | ||
241 | } | ||
242 | |||
243 | case frame::part::type::selection_preposition: | ||
244 | { | ||
245 | using vector_type = std::vector<std::string>; | ||
246 | _selection_preposition.preprestrs.~vector_type(); | ||
247 | |||
248 | break; | ||
249 | } | ||
250 | |||
251 | case frame::part::type::literal: | ||
252 | { | ||
253 | using string_type = std::string; | ||
254 | _literal.lexval.~string_type(); | ||
255 | |||
256 | break; | ||
257 | } | ||
258 | |||
259 | default: | ||
260 | { | ||
261 | // Nothing! | ||
262 | |||
263 | break; | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | |||
268 | std::string frame::part::get_role() const | ||
269 | { | ||
270 | assert(_type == frame::part::type::noun_phrase); | ||
271 | |||
272 | return _noun_phrase.role; | ||
273 | } | ||
274 | |||
275 | frame::selrestr frame::part::get_selrestrs() const | ||
276 | { | ||
277 | assert(_type == frame::part::type::noun_phrase); | ||
278 | |||
279 | return _noun_phrase.selrestrs; | ||
280 | } | ||
281 | |||
282 | std::set<std::string> frame::part::get_synrestrs() const | ||
283 | { | ||
284 | assert(_type == frame::part::type::noun_phrase); | ||
285 | |||
286 | return _noun_phrase.synrestrs; | ||
287 | } | ||
288 | |||
289 | std::vector<std::string> frame::part::get_choices() const | ||
290 | { | ||
291 | assert(_type == frame::part::type::literal_preposition); | ||
292 | |||
293 | return _literal_preposition.choices; | ||
294 | } | ||
295 | |||
296 | std::vector<std::string> frame::part::get_preprestrs() const | ||
297 | { | ||
298 | assert(_type == frame::part::type::selection_preposition); | ||
299 | |||
300 | return _selection_preposition.preprestrs; | ||
301 | } | ||
302 | |||
303 | std::string frame::part::get_literal() const | ||
304 | { | ||
305 | assert(_type == frame::part::type::literal); | ||
306 | |||
307 | return _literal.lexval; | ||
308 | } | ||
309 | |||
310 | std::vector<frame::part> frame::parts() const | ||
311 | { | ||
312 | return _parts; | ||
313 | } | ||
314 | |||
315 | std::map<std::string, frame::selrestr> frame::roles() const | ||
316 | { | ||
317 | return _roles; | ||
318 | } | ||
319 | |||
320 | }; | ||
diff --git a/lib/frame.h b/lib/frame.h new file mode 100644 index 0000000..fa57e1b --- /dev/null +++ b/lib/frame.h | |||
@@ -0,0 +1,118 @@ | |||
1 | #ifndef FRAME_H_9A5D90FE | ||
2 | #define FRAME_H_9A5D90FE | ||
3 | |||
4 | namespace verbly { | ||
5 | |||
6 | class frame_query; | ||
7 | |||
8 | class frame { | ||
9 | public: | ||
10 | class selrestr { | ||
11 | public: | ||
12 | enum class type { | ||
13 | empty, | ||
14 | singleton, | ||
15 | group | ||
16 | }; | ||
17 | |||
18 | type get_type() const; | ||
19 | selrestr(const selrestr& other); | ||
20 | ~selrestr(); | ||
21 | selrestr& operator=(const selrestr& other); | ||
22 | |||
23 | // Empty | ||
24 | selrestr(); | ||
25 | |||
26 | // Singleton | ||
27 | selrestr(std::string restriction, bool pos); | ||
28 | std::string get_restriction() const; | ||
29 | bool get_pos() const; | ||
30 | |||
31 | // Group | ||
32 | selrestr(std::list<selrestr> children, bool orlogic); | ||
33 | std::list<selrestr> get_children() const; | ||
34 | std::list<selrestr>::const_iterator begin() const; | ||
35 | std::list<selrestr>::const_iterator end() const; | ||
36 | bool get_orlogic() const; | ||
37 | |||
38 | private: | ||
39 | union { | ||
40 | struct { | ||
41 | bool pos; | ||
42 | std::string restriction; | ||
43 | } _singleton; | ||
44 | struct { | ||
45 | std::list<selrestr> children; | ||
46 | bool orlogic; | ||
47 | } _group; | ||
48 | }; | ||
49 | type _type; | ||
50 | }; | ||
51 | |||
52 | class part { | ||
53 | public: | ||
54 | enum class type { | ||
55 | noun_phrase, | ||
56 | verb, | ||
57 | literal_preposition, | ||
58 | selection_preposition, | ||
59 | adjective, | ||
60 | adverb, | ||
61 | literal | ||
62 | }; | ||
63 | |||
64 | type get_type() const; | ||
65 | part(const part& other); | ||
66 | ~part(); | ||
67 | |||
68 | // Noun phrase | ||
69 | std::string get_role() const; | ||
70 | selrestr get_selrestrs() const; | ||
71 | std::set<std::string> get_synrestrs() const; | ||
72 | |||
73 | // Literal preposition | ||
74 | std::vector<std::string> get_choices() const; | ||
75 | |||
76 | // Selection preposition | ||
77 | std::vector<std::string> get_preprestrs() const; | ||
78 | |||
79 | // Literal | ||
80 | std::string get_literal() const; | ||
81 | |||
82 | private: | ||
83 | friend class frame_query; | ||
84 | |||
85 | part(); | ||
86 | |||
87 | union { | ||
88 | struct { | ||
89 | std::string role; | ||
90 | selrestr selrestrs; | ||
91 | std::set<std::string> synrestrs; | ||
92 | } _noun_phrase; | ||
93 | struct { | ||
94 | std::vector<std::string> choices; | ||
95 | } _literal_preposition; | ||
96 | struct { | ||
97 | std::vector<std::string> preprestrs; | ||
98 | } _selection_preposition; | ||
99 | struct { | ||
100 | std::string lexval; | ||
101 | } _literal; | ||
102 | }; | ||
103 | type _type; | ||
104 | }; | ||
105 | |||
106 | std::vector<part> parts() const; | ||
107 | std::map<std::string, selrestr> roles() const; | ||
108 | |||
109 | private: | ||
110 | friend class frame_query; | ||
111 | |||
112 | std::vector<part> _parts; | ||
113 | std::map<std::string, selrestr> _roles; | ||
114 | }; | ||
115 | |||
116 | }; | ||
117 | |||
118 | #endif /* end of include guard: FRAME_H_9A5D90FE */ | ||
diff --git a/lib/frame_query.cpp b/lib/frame_query.cpp new file mode 100644 index 0000000..6583da4 --- /dev/null +++ b/lib/frame_query.cpp | |||
@@ -0,0 +1,142 @@ | |||
1 | #include "verbly.h" | ||
2 | #include <json.hpp> | ||
3 | |||
4 | using json = nlohmann::json; | ||
5 | |||
6 | namespace verbly { | ||
7 | |||
8 | frame_query::frame_query(const data& _data) : _data(_data) | ||
9 | { | ||
10 | |||
11 | } | ||
12 | |||
13 | frame_query& frame_query::for_verb(const verb& _v) | ||
14 | { | ||
15 | _for_verb.push_back(_v); | ||
16 | |||
17 | return *this; | ||
18 | } | ||
19 | |||
20 | frame::selrestr parse_selrestr(const json data) | ||
21 | { | ||
22 | if (data.find("children") != data.end()) | ||
23 | { | ||
24 | std::list<frame::selrestr> children; | ||
25 | std::transform(std::begin(data["children"]), std::end(data["children"]), std::back_inserter(children), &parse_selrestr); | ||
26 | |||
27 | return frame::selrestr{children, data["logic"] == "or"}; | ||
28 | } else if (data.find("type") != data.end()) | ||
29 | { | ||
30 | return frame::selrestr{data["type"].get<std::string>(), data["pos"].get<bool>()}; | ||
31 | } else { | ||
32 | return frame::selrestr{}; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | std::list<frame> frame_query::run() const | ||
37 | { | ||
38 | std::stringstream construct; | ||
39 | construct << "SELECT frames.data, groups.data FROM frames INNER JOIN groups ON frames.group_id = groups.group_id"; | ||
40 | |||
41 | if (!_for_verb.empty()) | ||
42 | { | ||
43 | std::list<std::string> clauses(_for_verb.size(), "verb_id = @VERID"); | ||
44 | construct << " WHERE frames.group_id IN (SELECT group_id FROM verb_groups WHERE "; | ||
45 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); | ||
46 | construct << ")"; | ||
47 | } | ||
48 | |||
49 | sqlite3_stmt* ppstmt; | ||
50 | std::string query = construct.str(); | ||
51 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
52 | { | ||
53 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
54 | } | ||
55 | |||
56 | for (auto verb : _for_verb) | ||
57 | { | ||
58 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VERID"), verb._id); | ||
59 | } | ||
60 | |||
61 | std::list<frame> output; | ||
62 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
63 | { | ||
64 | frame f; | ||
65 | |||
66 | std::string fdatat(reinterpret_cast<const char*>(sqlite3_column_blob(ppstmt, 0))); | ||
67 | const json fdata = json::parse(fdatat); | ||
68 | for (const auto& part : fdata) | ||
69 | { | ||
70 | frame::part p; | ||
71 | |||
72 | if (part["type"] == "np") | ||
73 | { | ||
74 | p._type = frame::part::type::noun_phrase; | ||
75 | new(&p._noun_phrase.role) std::string(part["role"].get<std::string>()); | ||
76 | new(&p._noun_phrase.selrestrs) frame::selrestr(parse_selrestr(part["selrestrs"])); | ||
77 | new(&p._noun_phrase.synrestrs) std::set<std::string>(); | ||
78 | for (auto synrestr : part["synrestrs"]) | ||
79 | { | ||
80 | p._noun_phrase.synrestrs.insert(synrestr.get<std::string>()); | ||
81 | } | ||
82 | } else if (part["type"] == "pp") | ||
83 | { | ||
84 | if (!part["values"].empty()) | ||
85 | { | ||
86 | p._type = frame::part::type::literal_preposition; | ||
87 | new(&p._literal_preposition.choices) std::vector<std::string>(); | ||
88 | for (auto choice : part["values"]) | ||
89 | { | ||
90 | p._literal_preposition.choices.push_back(choice.get<std::string>()); | ||
91 | } | ||
92 | } else if (!part["preprestrs"].empty()) | ||
93 | { | ||
94 | p._type = frame::part::type::selection_preposition; | ||
95 | new(&p._selection_preposition.preprestrs) std::vector<std::string>(); | ||
96 | for (auto preprestr : part["preprestrs"]) | ||
97 | { | ||
98 | p._selection_preposition.preprestrs.push_back(preprestr.get<std::string>()); | ||
99 | } | ||
100 | } | ||
101 | } else if (part["type"] == "v") | ||
102 | { | ||
103 | p._type = frame::part::type::verb; | ||
104 | } else if (part["type"] == "adj") | ||
105 | { | ||
106 | p._type = frame::part::type::adjective; | ||
107 | } else if (part["type"] == "adv") | ||
108 | { | ||
109 | p._type = frame::part::type::adverb; | ||
110 | } else if (part["type"] == "lex") | ||
111 | { | ||
112 | p._type = frame::part::type::literal; | ||
113 | new(&p._literal.lexval) std::string(part["value"].get<std::string>()); | ||
114 | } | ||
115 | |||
116 | f._parts.push_back(p); | ||
117 | } | ||
118 | |||
119 | std::string rdatat(reinterpret_cast<const char*>(sqlite3_column_blob(ppstmt, 1))); | ||
120 | const json rdata = json::parse(rdatat); | ||
121 | for (const auto& role : rdata) | ||
122 | { | ||
123 | std::string rt = role["type"]; | ||
124 | frame::selrestr rs; | ||
125 | |||
126 | if (role.find("selrestrs") != role.end()) | ||
127 | { | ||
128 | rs = parse_selrestr(role["selrestrs"]); | ||
129 | } | ||
130 | |||
131 | f._roles[rt] = rs; | ||
132 | } | ||
133 | |||
134 | output.push_back(f); | ||
135 | } | ||
136 | |||
137 | sqlite3_finalize(ppstmt); | ||
138 | |||
139 | return output; | ||
140 | } | ||
141 | |||
142 | }; | ||
diff --git a/lib/frame_query.h b/lib/frame_query.h new file mode 100644 index 0000000..dd11d16 --- /dev/null +++ b/lib/frame_query.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef FRAME_QUERY_H_334B9D47 | ||
2 | #define FRAME_QUERY_H_334B9D47 | ||
3 | |||
4 | namespace verbly { | ||
5 | |||
6 | class frame_query { | ||
7 | public: | ||
8 | frame_query(const data& _data); | ||
9 | |||
10 | frame_query& for_verb(const verb& _v); | ||
11 | |||
12 | std::list<frame> run() const; | ||
13 | |||
14 | private: | ||
15 | const data& _data; | ||
16 | std::list<verb> _for_verb; | ||
17 | }; | ||
18 | |||
19 | }; | ||
20 | |||
21 | #endif /* end of include guard: FRAME_QUERY_H_334B9D47 */ | ||
diff --git a/lib/noun.cpp b/lib/noun.cpp index 81e6613..f575117 100644 --- a/lib/noun.cpp +++ b/lib/noun.cpp | |||
@@ -1,7 +1,14 @@ | |||
1 | #include "verbly.h" | 1 | #include "verbly.h" |
2 | #include <set> | ||
3 | #include <iostream> | ||
2 | 4 | ||
3 | namespace verbly { | 5 | namespace verbly { |
4 | 6 | ||
7 | noun::noun() | ||
8 | { | ||
9 | |||
10 | } | ||
11 | |||
5 | noun::noun(const data& _data, int _id) : word(_data, _id) | 12 | noun::noun(const data& _data, int _id) : word(_data, _id) |
6 | { | 13 | { |
7 | 14 | ||
@@ -9,1036 +16,147 @@ namespace verbly { | |||
9 | 16 | ||
10 | std::string noun::base_form() const | 17 | std::string noun::base_form() const |
11 | { | 18 | { |
19 | assert(_valid == true); | ||
20 | |||
12 | return _singular; | 21 | return _singular; |
13 | } | 22 | } |
14 | 23 | ||
15 | std::string noun::singular_form() const | 24 | std::string noun::singular_form() const |
16 | { | 25 | { |
26 | assert(_valid == true); | ||
27 | |||
17 | return _singular; | 28 | return _singular; |
18 | } | 29 | } |
19 | 30 | ||
20 | std::string noun::plural_form() const | 31 | std::string noun::plural_form() const |
21 | { | 32 | { |
33 | assert(_valid == true); | ||
34 | |||
22 | return _plural; | 35 | return _plural; |
23 | } | 36 | } |
24 | 37 | ||
25 | bool noun::has_plural_form() const | 38 | bool noun::has_plural_form() const |
26 | { | 39 | { |
40 | assert(_valid == true); | ||
41 | |||
27 | return !_plural.empty(); | 42 | return !_plural.empty(); |
28 | } | 43 | } |
29 | 44 | ||
30 | noun_query noun::hypernyms() const | 45 | noun_query noun::hypernyms() const |
31 | { | 46 | { |
32 | return _data.nouns().hypernym_of(*this); | 47 | assert(_valid == true); |
33 | } | ||
34 | |||
35 | noun_query noun::hyponyms() const | ||
36 | { | ||
37 | return _data.nouns().hyponym_of(*this); | ||
38 | } | ||
39 | |||
40 | noun_query noun::part_meronyms() const | ||
41 | { | ||
42 | return _data.nouns().part_meronym_of(*this); | ||
43 | } | ||
44 | |||
45 | noun_query noun::part_holonyms() const | ||
46 | { | ||
47 | return _data.nouns().part_holonym_of(*this); | ||
48 | } | ||
49 | |||
50 | noun_query noun::substance_meronyms() const | ||
51 | { | ||
52 | return _data.nouns().substance_meronym_of(*this); | ||
53 | } | ||
54 | |||
55 | noun_query noun::substance_holonyms() const | ||
56 | { | ||
57 | return _data.nouns().substance_holonym_of(*this); | ||
58 | } | ||
59 | |||
60 | noun_query noun::member_meronyms() const | ||
61 | { | ||
62 | return _data.nouns().member_meronym_of(*this); | ||
63 | } | ||
64 | |||
65 | noun_query noun::member_holonyms() const | ||
66 | { | ||
67 | return _data.nouns().member_holonym_of(*this); | ||
68 | } | ||
69 | |||
70 | noun_query noun::classes() const | ||
71 | { | ||
72 | return _data.nouns().class_of(*this); | ||
73 | } | ||
74 | |||
75 | noun_query noun::instances() const | ||
76 | { | ||
77 | return _data.nouns().instance_of(*this); | ||
78 | } | ||
79 | |||
80 | noun_query noun::synonyms() const | ||
81 | { | ||
82 | return _data.nouns().synonym_of(*this); | ||
83 | } | ||
84 | |||
85 | noun_query noun::antonyms() const | ||
86 | { | ||
87 | return _data.nouns().antonym_of(*this); | ||
88 | } | ||
89 | |||
90 | adjective_query noun::pertainyms() const | ||
91 | { | ||
92 | return _data.adjectives().pertainym_of(*this); | ||
93 | } | ||
94 | |||
95 | adjective_query noun::variations() const | ||
96 | { | ||
97 | return _data.adjectives().variant_of(*this); | ||
98 | } | ||
99 | |||
100 | noun_query::noun_query(const data& _data) : _data(_data) | ||
101 | { | ||
102 | |||
103 | } | ||
104 | |||
105 | noun_query& noun_query::limit(int _limit) | ||
106 | { | ||
107 | if ((_limit > 0) || (_limit == unlimited)) | ||
108 | { | ||
109 | this->_limit = _limit; | ||
110 | } | ||
111 | |||
112 | return *this; | ||
113 | } | ||
114 | |||
115 | noun_query& noun_query::random(bool _random) | ||
116 | { | ||
117 | this->_random = _random; | ||
118 | |||
119 | return *this; | ||
120 | } | ||
121 | |||
122 | noun_query& noun_query::except(const noun& _word) | ||
123 | { | ||
124 | _except.push_back(_word); | ||
125 | |||
126 | return *this; | ||
127 | } | ||
128 | |||
129 | noun_query& noun_query::rhymes_with(const word& _word) | ||
130 | { | ||
131 | for (auto rhyme : _word.rhyme_phonemes()) | ||
132 | { | ||
133 | _rhymes.push_back(rhyme); | ||
134 | } | ||
135 | |||
136 | if (dynamic_cast<const noun*>(&_word) != nullptr) | ||
137 | { | ||
138 | _except.push_back(dynamic_cast<const noun&>(_word)); | ||
139 | } | ||
140 | |||
141 | return *this; | ||
142 | } | ||
143 | |||
144 | noun_query& noun_query::has_pronunciation(bool _has_prn) | ||
145 | { | ||
146 | this->_has_prn = _has_prn; | ||
147 | |||
148 | return *this; | ||
149 | } | ||
150 | |||
151 | noun_query& noun_query::is_hypernym(bool _arg) | ||
152 | { | ||
153 | _is_hypernym = _arg; | ||
154 | |||
155 | return *this; | ||
156 | } | ||
157 | |||
158 | noun_query& noun_query::hypernym_of(const noun& _noun) | ||
159 | { | ||
160 | _hypernym_of.push_back(_noun); | ||
161 | |||
162 | return *this; | ||
163 | } | ||
164 | |||
165 | noun_query& noun_query::not_hypernym_of(const noun& _noun) | ||
166 | { | ||
167 | _not_hypernym_of.push_back(_noun); | ||
168 | |||
169 | return *this; | ||
170 | } | ||
171 | |||
172 | noun_query& noun_query::is_hyponym(bool _arg) | ||
173 | { | ||
174 | _is_hyponym = _arg; | ||
175 | |||
176 | return *this; | ||
177 | } | ||
178 | |||
179 | noun_query& noun_query::hyponym_of(const noun& _noun) | ||
180 | { | ||
181 | _hyponym_of.push_back(_noun); | ||
182 | |||
183 | return *this; | ||
184 | } | ||
185 | |||
186 | noun_query& noun_query::not_hyponym_of(const noun& _noun) | ||
187 | { | ||
188 | _not_hyponym_of.push_back(_noun); | ||
189 | |||
190 | return *this; | ||
191 | } | ||
192 | |||
193 | noun_query& noun_query::is_part_meronym(bool _arg) | ||
194 | { | ||
195 | _is_part_meronym = _arg; | ||
196 | |||
197 | return *this; | ||
198 | } | ||
199 | |||
200 | noun_query& noun_query::part_meronym_of(const noun& _noun) | ||
201 | { | ||
202 | _part_meronym_of.push_back(_noun); | ||
203 | 48 | ||
204 | return *this; | 49 | return _data->nouns().hypernym_of(*this); |
205 | } | 50 | } |
206 | 51 | ||
207 | noun_query& noun_query::not_part_meronym_of(const noun& _noun) | 52 | noun_query noun::full_hypernyms() const |
208 | { | 53 | { |
209 | _not_part_meronym_of.push_back(_noun); | 54 | assert(_valid == true); |
210 | 55 | ||
211 | return *this; | 56 | return _data->nouns().full_hypernym_of(*this); |
212 | } | 57 | } |
213 | 58 | ||
214 | noun_query& noun_query::is_part_holonym(bool _arg) | 59 | noun_query noun::hyponyms() const |
215 | { | ||
216 | _is_part_holonym = _arg; | ||
217 | |||
218 | return *this; | ||
219 | } | ||
220 | |||
221 | noun_query& noun_query::part_holonym_of(const noun& _noun) | ||
222 | { | ||
223 | _part_holonym_of.push_back(_noun); | ||
224 | |||
225 | return *this; | ||
226 | } | ||
227 | |||
228 | noun_query& noun_query::not_part_holonym_of(const noun& _noun) | ||
229 | { | ||
230 | _not_part_holonym_of.push_back(_noun); | ||
231 | |||
232 | return *this; | ||
233 | } | ||
234 | |||
235 | noun_query& noun_query::is_substance_meronym(bool _arg) | ||
236 | { | ||
237 | _is_substance_meronym = _arg; | ||
238 | |||
239 | return *this; | ||
240 | } | ||
241 | |||
242 | noun_query& noun_query::substance_meronym_of(const noun& _noun) | ||
243 | { | ||
244 | _substance_meronym_of.push_back(_noun); | ||
245 | |||
246 | return *this; | ||
247 | } | ||
248 | |||
249 | noun_query& noun_query::not_substance_meronym_of(const noun& _noun) | ||
250 | { | ||
251 | _not_substance_meronym_of.push_back(_noun); | ||
252 | |||
253 | return *this; | ||
254 | } | ||
255 | |||
256 | noun_query& noun_query::is_substance_holonym(bool _arg) | ||
257 | { | ||
258 | _is_substance_holonym = _arg; | ||
259 | |||
260 | return *this; | ||
261 | } | ||
262 | |||
263 | noun_query& noun_query::substance_holonym_of(const noun& _noun) | ||
264 | { | ||
265 | _substance_holonym_of.push_back(_noun); | ||
266 | |||
267 | return *this; | ||
268 | } | ||
269 | |||
270 | noun_query& noun_query::not_substance_holonym_of(const noun& _noun) | ||
271 | { | ||
272 | _not_substance_holonym_of.push_back(_noun); | ||
273 | |||
274 | return *this; | ||
275 | } | ||
276 | |||
277 | noun_query& noun_query::is_member_meronym(bool _arg) | ||
278 | { | ||
279 | _is_member_meronym = _arg; | ||
280 | |||
281 | return *this; | ||
282 | } | ||
283 | |||
284 | noun_query& noun_query::member_meronym_of(const noun& _noun) | ||
285 | { | ||
286 | _member_meronym_of.push_back(_noun); | ||
287 | |||
288 | return *this; | ||
289 | } | ||
290 | |||
291 | noun_query& noun_query::not_member_meronym_of(const noun& _noun) | ||
292 | { | ||
293 | _not_member_meronym_of.push_back(_noun); | ||
294 | |||
295 | return *this; | ||
296 | } | ||
297 | |||
298 | noun_query& noun_query::is_member_holonym(bool _arg) | ||
299 | { | ||
300 | _is_member_holonym = _arg; | ||
301 | |||
302 | return *this; | ||
303 | } | ||
304 | |||
305 | noun_query& noun_query::member_holonym_of(const noun& _noun) | ||
306 | { | ||
307 | _member_holonym_of.push_back(_noun); | ||
308 | |||
309 | return *this; | ||
310 | } | ||
311 | |||
312 | noun_query& noun_query::not_member_holonym_of(const noun& _noun) | ||
313 | { | ||
314 | _not_member_holonym_of.push_back(_noun); | ||
315 | |||
316 | return *this; | ||
317 | } | ||
318 | |||
319 | noun_query& noun_query::is_proper(bool _arg) | ||
320 | { | ||
321 | _is_proper = _arg; | ||
322 | |||
323 | return *this; | ||
324 | } | ||
325 | |||
326 | noun_query& noun_query::is_not_proper(bool _arg) | ||
327 | { | ||
328 | _is_not_proper = _arg; | ||
329 | |||
330 | return *this; | ||
331 | } | ||
332 | |||
333 | noun_query& noun_query::is_instance(bool _arg) | ||
334 | { | ||
335 | _is_instance = _arg; | ||
336 | |||
337 | return *this; | ||
338 | } | ||
339 | |||
340 | noun_query& noun_query::instance_of(const noun& _noun) | ||
341 | { | ||
342 | _instance_of.push_back(_noun); | ||
343 | |||
344 | return *this; | ||
345 | } | ||
346 | |||
347 | noun_query& noun_query::not_instance_of(const noun& _noun) | ||
348 | { | ||
349 | _not_instance_of.push_back(_noun); | ||
350 | |||
351 | return *this; | ||
352 | } | ||
353 | |||
354 | noun_query& noun_query::is_class(bool _arg) | ||
355 | { | ||
356 | _is_class = _arg; | ||
357 | |||
358 | return *this; | ||
359 | } | ||
360 | |||
361 | noun_query& noun_query::class_of(const noun& _noun) | ||
362 | { | 60 | { |
363 | _class_of.push_back(_noun); | 61 | assert(_valid == true); |
364 | 62 | ||
365 | return *this; | 63 | return _data->nouns().hyponym_of(*this); |
366 | } | 64 | } |
367 | 65 | ||
368 | noun_query& noun_query::not_class_of(const noun& _noun) | 66 | noun_query noun::full_hyponyms() const |
369 | { | 67 | { |
370 | _not_class_of.push_back(_noun); | 68 | assert(_valid == true); |
371 | 69 | ||
372 | return *this; | 70 | return _data->nouns().full_hyponym_of(*this); |
373 | } | 71 | } |
374 | 72 | ||
375 | noun_query& noun_query::has_synonyms(bool _arg) | 73 | noun_query noun::part_meronyms() const |
376 | { | 74 | { |
377 | _has_synonyms = _arg; | 75 | assert(_valid == true); |
378 | 76 | ||
379 | return *this; | 77 | return _data->nouns().part_meronym_of(*this); |
380 | } | 78 | } |
381 | 79 | ||
382 | noun_query& noun_query::synonym_of(const noun& _noun) | 80 | noun_query noun::part_holonyms() const |
383 | { | 81 | { |
384 | _synonym_of.push_back(_noun); | 82 | assert(_valid == true); |
385 | 83 | ||
386 | return *this; | 84 | return _data->nouns().part_holonym_of(*this); |
387 | } | 85 | } |
388 | 86 | ||
389 | noun_query& noun_query::not_synonym_of(const noun& _noun) | 87 | noun_query noun::substance_meronyms() const |
390 | { | 88 | { |
391 | _not_synonym_of.push_back(_noun); | 89 | assert(_valid == true); |
392 | 90 | ||
393 | return *this; | 91 | return _data->nouns().substance_meronym_of(*this); |
394 | } | 92 | } |
395 | 93 | ||
396 | noun_query& noun_query::has_antonyms(bool _arg) | 94 | noun_query noun::substance_holonyms() const |
397 | { | 95 | { |
398 | _has_antonyms = _arg; | 96 | assert(_valid == true); |
399 | 97 | ||
400 | return *this; | 98 | return _data->nouns().substance_holonym_of(*this); |
401 | } | 99 | } |
402 | 100 | ||
403 | noun_query& noun_query::antonym_of(const noun& _noun) | 101 | noun_query noun::member_meronyms() const |
404 | { | 102 | { |
405 | _antonym_of.push_back(_noun); | 103 | assert(_valid == true); |
406 | 104 | ||
407 | return *this; | 105 | return _data->nouns().member_meronym_of(*this); |
408 | } | 106 | } |
409 | 107 | ||
410 | noun_query& noun_query::not_antonym_of(const noun& _noun) | 108 | noun_query noun::member_holonyms() const |
411 | { | 109 | { |
412 | _not_antonym_of.push_back(_noun); | 110 | assert(_valid == true); |
413 | 111 | ||
414 | return *this; | 112 | return _data->nouns().member_holonym_of(*this); |
415 | } | 113 | } |
416 | 114 | ||
417 | noun_query& noun_query::has_pertainym(bool _arg) | 115 | noun_query noun::classes() const |
418 | { | 116 | { |
419 | _has_pertainym = _arg; | 117 | assert(_valid == true); |
420 | 118 | ||
421 | return *this; | 119 | return _data->nouns().class_of(*this); |
422 | } | 120 | } |
423 | 121 | ||
424 | noun_query& noun_query::anti_pertainym_of(const adjective& _adj) | 122 | noun_query noun::instances() const |
425 | { | 123 | { |
426 | _anti_pertainym_of.push_back(_adj); | 124 | assert(_valid == true); |
427 | 125 | ||
428 | return *this; | 126 | return _data->nouns().instance_of(*this); |
429 | } | 127 | } |
430 | 128 | ||
431 | noun_query& noun_query::is_attribute(bool _arg) | 129 | noun_query noun::synonyms() const |
432 | { | 130 | { |
433 | _is_attribute = _arg; | 131 | assert(_valid == true); |
434 | 132 | ||
435 | return *this; | 133 | return _data->nouns().synonym_of(*this); |
436 | } | 134 | } |
437 | 135 | ||
438 | noun_query& noun_query::attribute_of(const adjective& _adj) | 136 | noun_query noun::antonyms() const |
439 | { | 137 | { |
440 | _attribute_of.push_back(_adj); | 138 | assert(_valid == true); |
441 | 139 | ||
442 | return *this; | 140 | return _data->nouns().antonym_of(*this); |
443 | } | 141 | } |
444 | 142 | ||
445 | noun_query& noun_query::derived_from(const word& _w) | 143 | adjective_query noun::pertainyms() const |
446 | { | 144 | { |
447 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 145 | assert(_valid == true); |
448 | { | ||
449 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
450 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
451 | { | ||
452 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
453 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
454 | { | ||
455 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
456 | } | ||
457 | 146 | ||
458 | return *this; | 147 | return _data->adjectives().pertainym_of(*this); |
459 | } | 148 | } |
460 | 149 | ||
461 | noun_query& noun_query::not_derived_from(const word& _w) | 150 | adjective_query noun::variations() const |
462 | { | 151 | { |
463 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | 152 | assert(_valid == true); |
464 | { | ||
465 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
466 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
467 | { | ||
468 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
469 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
470 | { | ||
471 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
472 | } | ||
473 | 153 | ||
474 | return *this; | 154 | return _data->adjectives().variant_of(*this); |
475 | } | 155 | } |
476 | 156 | ||
477 | std::list<noun> noun_query::run() const | 157 | bool noun::operator<(const noun& other) const |
478 | { | 158 | { |
479 | std::stringstream construct; | 159 | return _id < other._id; |
480 | construct << "SELECT noun_id, singular, plural FROM nouns"; | ||
481 | std::list<std::string> conditions; | ||
482 | |||
483 | if (_has_prn) | ||
484 | { | ||
485 | conditions.push_back("noun_id IN (SELECT noun_id FROM noun_pronunciations)"); | ||
486 | } | ||
487 | |||
488 | if (!_rhymes.empty()) | ||
489 | { | ||
490 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
491 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
492 | conditions.push_back(cond); | ||
493 | } | ||
494 | |||
495 | for (auto except : _except) | ||
496 | { | ||
497 | conditions.push_back("noun_id != @EXCID"); | ||
498 | } | ||
499 | |||
500 | if (_is_hypernym) | ||
501 | { | ||
502 | conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)"); | ||
503 | } | ||
504 | |||
505 | if (!_hypernym_of.empty()) | ||
506 | { | ||
507 | std::list<std::string> clauses(_hypernym_of.size(), "hyponym_id = @HYPO"); | ||
508 | std::string cond = "noun_id IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
509 | conditions.push_back(cond); | ||
510 | } | ||
511 | |||
512 | if (!_not_hypernym_of.empty()) | ||
513 | { | ||
514 | std::list<std::string> clauses(_not_hypernym_of.size(), "hyponym_id = @NHYPO"); | ||
515 | std::string cond = "noun_id NOT IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
516 | conditions.push_back(cond); | ||
517 | } | ||
518 | |||
519 | if (_is_hyponym) | ||
520 | { | ||
521 | conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)"); | ||
522 | } | ||
523 | |||
524 | if (!_hyponym_of.empty()) | ||
525 | { | ||
526 | std::list<std::string> clauses(_hyponym_of.size(), "hypernym_id = @HYPER"); | ||
527 | std::string cond = "noun_id IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
528 | conditions.push_back(cond); | ||
529 | } | ||
530 | |||
531 | if (!_not_hyponym_of.empty()) | ||
532 | { | ||
533 | std::list<std::string> clauses(_not_hyponym_of.size(), "hypernym_id = @NHYPER"); | ||
534 | std::string cond = "noun_id NOT IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
535 | conditions.push_back(cond); | ||
536 | } | ||
537 | |||
538 | if (_is_part_meronym) | ||
539 | { | ||
540 | conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)"); | ||
541 | } | ||
542 | |||
543 | if (!_part_meronym_of.empty()) | ||
544 | { | ||
545 | std::list<std::string> clauses(_part_meronym_of.size(), "holonym_id = @PHOLO"); | ||
546 | std::string cond = "noun_id IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
547 | conditions.push_back(cond); | ||
548 | } | ||
549 | |||
550 | if (!_not_part_meronym_of.empty()) | ||
551 | { | ||
552 | std::list<std::string> clauses(_not_part_meronym_of.size(), "holonym_id = @NPHOLO"); | ||
553 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
554 | conditions.push_back(cond); | ||
555 | } | ||
556 | |||
557 | if (_is_part_holonym) | ||
558 | { | ||
559 | conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)"); | ||
560 | } | ||
561 | |||
562 | if (!_part_holonym_of.empty()) | ||
563 | { | ||
564 | std::list<std::string> clauses(_part_holonym_of.size(), "meronym_id = @PMERO"); | ||
565 | std::string cond = "noun_id IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
566 | conditions.push_back(cond); | ||
567 | } | ||
568 | |||
569 | if (!_not_part_holonym_of.empty()) | ||
570 | { | ||
571 | std::list<std::string> clauses(_not_part_holonym_of.size(), "meronym_id = @NPMERO"); | ||
572 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
573 | conditions.push_back(cond); | ||
574 | } | ||
575 | |||
576 | if (_is_substance_meronym) | ||
577 | { | ||
578 | conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)"); | ||
579 | } | ||
580 | |||
581 | if (!_substance_meronym_of.empty()) | ||
582 | { | ||
583 | std::list<std::string> clauses(_substance_meronym_of.size(), "holonym_id = @SHOLO"); | ||
584 | std::string cond = "noun_id IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
585 | conditions.push_back(cond); | ||
586 | } | ||
587 | |||
588 | if (!_not_substance_meronym_of.empty()) | ||
589 | { | ||
590 | std::list<std::string> clauses(_not_substance_meronym_of.size(), "holonym_id = @NSHOLO"); | ||
591 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
592 | conditions.push_back(cond); | ||
593 | } | ||
594 | |||
595 | if (_is_substance_holonym) | ||
596 | { | ||
597 | conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)"); | ||
598 | } | ||
599 | |||
600 | if (!_substance_holonym_of.empty()) | ||
601 | { | ||
602 | std::list<std::string> clauses(_substance_holonym_of.size(), "meronym_id = @SMERO"); | ||
603 | std::string cond = "noun_id IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
604 | conditions.push_back(cond); | ||
605 | } | ||
606 | |||
607 | if (!_not_substance_holonym_of.empty()) | ||
608 | { | ||
609 | std::list<std::string> clauses(_not_substance_holonym_of.size(), "meronym_id = @NSMERO"); | ||
610 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
611 | conditions.push_back(cond); | ||
612 | } | ||
613 | |||
614 | if (_is_member_meronym) | ||
615 | { | ||
616 | conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)"); | ||
617 | } | ||
618 | |||
619 | if (!_member_meronym_of.empty()) | ||
620 | { | ||
621 | std::list<std::string> clauses(_member_meronym_of.size(), "holonym_id = @MHOLO"); | ||
622 | std::string cond = "noun_id IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
623 | conditions.push_back(cond); | ||
624 | } | ||
625 | |||
626 | if (!_not_member_meronym_of.empty()) | ||
627 | { | ||
628 | std::list<std::string> clauses(_not_member_meronym_of.size(), "holonym_id = @NMHOLO"); | ||
629 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
630 | conditions.push_back(cond); | ||
631 | } | ||
632 | |||
633 | if (_is_member_holonym) | ||
634 | { | ||
635 | conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)"); | ||
636 | } | ||
637 | |||
638 | if (!_member_holonym_of.empty()) | ||
639 | { | ||
640 | std::list<std::string> clauses(_member_holonym_of.size(), "meronym_id = @MMERO"); | ||
641 | std::string cond = "noun_id IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
642 | conditions.push_back(cond); | ||
643 | } | ||
644 | |||
645 | if (!_not_member_holonym_of.empty()) | ||
646 | { | ||
647 | std::list<std::string> clauses(_not_member_holonym_of.size(), "meronym_id = @NMMERO"); | ||
648 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
649 | conditions.push_back(cond); | ||
650 | } | ||
651 | |||
652 | if (_is_proper) | ||
653 | { | ||
654 | conditions.push_back("proper = 1"); | ||
655 | } | ||
656 | |||
657 | if (_is_not_proper) | ||
658 | { | ||
659 | conditions.push_back("proper = 0"); | ||
660 | } | ||
661 | |||
662 | if (_is_instance) | ||
663 | { | ||
664 | conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)"); | ||
665 | } | ||
666 | |||
667 | if (!_instance_of.empty()) | ||
668 | { | ||
669 | std::list<std::string> clauses(_instance_of.size(), "class_id = @CLSID"); | ||
670 | std::string cond = "noun_id IN (SELECT instance_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
671 | conditions.push_back(cond); | ||
672 | } | ||
673 | |||
674 | if (!_not_instance_of.empty()) | ||
675 | { | ||
676 | std::list<std::string> clauses(_not_instance_of.size(), "class_id = @NCLSID"); | ||
677 | std::string cond = "noun_id NOT IN (SELECT instance_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
678 | conditions.push_back(cond); | ||
679 | } | ||
680 | |||
681 | if (_is_class) | ||
682 | { | ||
683 | conditions.push_back("noun_id IN (SELECT class_id FROM instantiation)"); | ||
684 | } | ||
685 | |||
686 | if (!_class_of.empty()) | ||
687 | { | ||
688 | std::list<std::string> clauses(_class_of.size(), "instance_id = @INSID"); | ||
689 | std::string cond = "noun_id IN (SELECT class_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
690 | conditions.push_back(cond); | ||
691 | } | ||
692 | |||
693 | if (!_not_class_of.empty()) | ||
694 | { | ||
695 | std::list<std::string> clauses(_not_class_of.size(), "instance_id = @NINSID"); | ||
696 | std::string cond = "noun_id NOT IN (SELECT class_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
697 | conditions.push_back(cond); | ||
698 | } | ||
699 | |||
700 | if (_has_synonyms) | ||
701 | { | ||
702 | conditions.push_back("noun_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); | ||
703 | } | ||
704 | |||
705 | if (!_synonym_of.empty()) | ||
706 | { | ||
707 | std::list<std::string> clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); | ||
708 | std::string cond = "noun_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
709 | conditions.push_back(cond); | ||
710 | } | ||
711 | |||
712 | if (!_not_synonym_of.empty()) | ||
713 | { | ||
714 | std::list<std::string> clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); | ||
715 | std::string cond = "noun_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
716 | conditions.push_back(cond); | ||
717 | } | ||
718 | |||
719 | if (_has_antonyms) | ||
720 | { | ||
721 | conditions.push_back("noun_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); | ||
722 | } | ||
723 | |||
724 | if (!_antonym_of.empty()) | ||
725 | { | ||
726 | std::list<std::string> clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); | ||
727 | std::string cond = "noun_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
728 | conditions.push_back(cond); | ||
729 | } | ||
730 | |||
731 | if (!_not_antonym_of.empty()) | ||
732 | { | ||
733 | std::list<std::string> clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); | ||
734 | std::string cond = "noun_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
735 | conditions.push_back(cond); | ||
736 | } | ||
737 | |||
738 | if (_has_pertainym) | ||
739 | { | ||
740 | conditions.push_back("noun_id IN (SELECT noun_id FROM pertainymy)"); | ||
741 | } | ||
742 | |||
743 | if (!_anti_pertainym_of.empty()) | ||
744 | { | ||
745 | std::list<std::string> clauses(_anti_pertainym_of.size(), "pertainym_id = @PERID"); | ||
746 | std::string cond = "noun_id IN (SELECT noun_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
747 | conditions.push_back(cond); | ||
748 | } | ||
749 | |||
750 | if (_is_attribute) | ||
751 | { | ||
752 | conditions.push_back("noun_id IN (SELECT noun_id FROM variation)"); | ||
753 | } | ||
754 | |||
755 | if (!_attribute_of.empty()) | ||
756 | { | ||
757 | std::list<std::string> clauses(_attribute_of.size(), "adjective_id = @VALID"); | ||
758 | std::string cond = "noun_id IN (SELECT noun_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
759 | conditions.push_back(cond); | ||
760 | } | ||
761 | |||
762 | if (!_derived_from_adjective.empty()) | ||
763 | { | ||
764 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); | ||
765 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
766 | conditions.push_back(cond); | ||
767 | } | ||
768 | |||
769 | if (!_not_derived_from_adjective.empty()) | ||
770 | { | ||
771 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); | ||
772 | std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
773 | conditions.push_back(cond); | ||
774 | } | ||
775 | |||
776 | if (!_derived_from_adverb.empty()) | ||
777 | { | ||
778 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); | ||
779 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
780 | conditions.push_back(cond); | ||
781 | } | ||
782 | |||
783 | if (!_not_derived_from_adverb.empty()) | ||
784 | { | ||
785 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); | ||
786 | std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
787 | conditions.push_back(cond); | ||
788 | } | ||
789 | |||
790 | if (!_derived_from_noun.empty()) | ||
791 | { | ||
792 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_2_id = @DERN"); | ||
793 | std::string cond = "noun_id IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
794 | conditions.push_back(cond); | ||
795 | } | ||
796 | |||
797 | if (!_not_derived_from_noun.empty()) | ||
798 | { | ||
799 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_2_id = @NDERN"); | ||
800 | std::string cond = "noun_id NOT IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
801 | conditions.push_back(cond); | ||
802 | } | ||
803 | |||
804 | if (!conditions.empty()) | ||
805 | { | ||
806 | construct << " WHERE "; | ||
807 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
808 | } | ||
809 | |||
810 | if (_random) | ||
811 | { | ||
812 | construct << " ORDER BY RANDOM()"; | ||
813 | } | ||
814 | |||
815 | if (_limit != unlimited) | ||
816 | { | ||
817 | construct << " LIMIT " << _limit; | ||
818 | } | ||
819 | |||
820 | sqlite3_stmt* ppstmt; | ||
821 | std::string query = construct.str(); | ||
822 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
823 | { | ||
824 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
825 | } | ||
826 | |||
827 | if (!_rhymes.empty()) | ||
828 | { | ||
829 | int i = 0; | ||
830 | for (auto rhyme : _rhymes) | ||
831 | { | ||
832 | std::string rhymer = "%" + rhyme; | ||
833 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
834 | |||
835 | i++; | ||
836 | } | ||
837 | } | ||
838 | |||
839 | for (auto except : _except) | ||
840 | { | ||
841 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
842 | } | ||
843 | |||
844 | for (auto hyponym : _hypernym_of) | ||
845 | { | ||
846 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPO"), hyponym._id); | ||
847 | } | ||
848 | |||
849 | for (auto hyponym : _not_hypernym_of) | ||
850 | { | ||
851 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NHYPO"), hyponym._id); | ||
852 | } | ||
853 | |||
854 | for (auto hypernym : _hyponym_of) | ||
855 | { | ||
856 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPER"), hypernym._id); | ||
857 | } | ||
858 | |||
859 | for (auto hypernym : _not_hyponym_of) | ||
860 | { | ||
861 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NHYPER"), hypernym._id); | ||
862 | } | ||
863 | |||
864 | for (auto holonym : _part_meronym_of) | ||
865 | { | ||
866 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PHOLO"), holonym._id); | ||
867 | } | ||
868 | |||
869 | for (auto holonym : _not_part_meronym_of) | ||
870 | { | ||
871 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NPHOLO"), holonym._id); | ||
872 | } | ||
873 | |||
874 | for (auto meronym : _part_holonym_of) | ||
875 | { | ||
876 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PMERO"), meronym._id); | ||
877 | } | ||
878 | |||
879 | for (auto meronym : _not_part_holonym_of) | ||
880 | { | ||
881 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NPMERO"), meronym._id); | ||
882 | } | ||
883 | |||
884 | for (auto holonym : _substance_meronym_of) | ||
885 | { | ||
886 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SHOLO"), holonym._id); | ||
887 | } | ||
888 | |||
889 | for (auto holonym : _not_substance_meronym_of) | ||
890 | { | ||
891 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSHOLO"), holonym._id); | ||
892 | } | ||
893 | |||
894 | for (auto meronym : _substance_holonym_of) | ||
895 | { | ||
896 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SMERO"), meronym._id); | ||
897 | } | ||
898 | |||
899 | for (auto meronym : _not_substance_holonym_of) | ||
900 | { | ||
901 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSMERO"), meronym._id); | ||
902 | } | ||
903 | |||
904 | for (auto holonym : _member_meronym_of) | ||
905 | { | ||
906 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MHOLO"), holonym._id); | ||
907 | } | ||
908 | |||
909 | for (auto holonym : _not_member_meronym_of) | ||
910 | { | ||
911 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NMHOLO"), holonym._id); | ||
912 | } | ||
913 | |||
914 | for (auto meronym : _member_holonym_of) | ||
915 | { | ||
916 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MMERO"), meronym._id); | ||
917 | } | ||
918 | |||
919 | for (auto meronym : _not_member_holonym_of) | ||
920 | { | ||
921 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NMMERO"), meronym._id); | ||
922 | } | ||
923 | |||
924 | for (auto cls : _instance_of) | ||
925 | { | ||
926 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@CLSID"), cls._id); | ||
927 | } | ||
928 | |||
929 | for (auto cls : _not_instance_of) | ||
930 | { | ||
931 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NCLSID"), cls._id); | ||
932 | } | ||
933 | |||
934 | for (auto inst : _class_of) | ||
935 | { | ||
936 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@INSID"), inst._id); | ||
937 | } | ||
938 | |||
939 | for (auto inst : _not_class_of) | ||
940 | { | ||
941 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NINSID"), inst._id); | ||
942 | } | ||
943 | |||
944 | for (auto synonym : _synonym_of) | ||
945 | { | ||
946 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
947 | } | ||
948 | |||
949 | for (auto synonym : _not_synonym_of) | ||
950 | { | ||
951 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
952 | } | ||
953 | |||
954 | for (auto antonym : _antonym_of) | ||
955 | { | ||
956 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
957 | } | ||
958 | |||
959 | for (auto antonym : _not_antonym_of) | ||
960 | { | ||
961 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
962 | } | ||
963 | |||
964 | for (auto pertainym : _anti_pertainym_of) | ||
965 | { | ||
966 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PERID"), pertainym._id); | ||
967 | } | ||
968 | |||
969 | for (auto value : _attribute_of) | ||
970 | { | ||
971 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VALID"), value._id); | ||
972 | } | ||
973 | |||
974 | for (auto adj : _derived_from_adjective) | ||
975 | { | ||
976 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
977 | } | ||
978 | |||
979 | for (auto adj : _not_derived_from_adjective) | ||
980 | { | ||
981 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
982 | } | ||
983 | |||
984 | for (auto adv : _derived_from_adverb) | ||
985 | { | ||
986 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
987 | } | ||
988 | |||
989 | for (auto adv : _not_derived_from_adverb) | ||
990 | { | ||
991 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
992 | } | ||
993 | |||
994 | for (auto n : _derived_from_noun) | ||
995 | { | ||
996 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
997 | } | ||
998 | |||
999 | for (auto n : _not_derived_from_noun) | ||
1000 | { | ||
1001 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
1002 | } | ||
1003 | |||
1004 | std::list<noun> output; | ||
1005 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
1006 | { | ||
1007 | noun tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
1008 | tnc._singular = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
1009 | |||
1010 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
1011 | { | ||
1012 | tnc._plural = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
1013 | } | ||
1014 | |||
1015 | output.push_back(tnc); | ||
1016 | } | ||
1017 | |||
1018 | sqlite3_finalize(ppstmt); | ||
1019 | |||
1020 | for (auto& noun : output) | ||
1021 | { | ||
1022 | query = "SELECT pronunciation FROM noun_pronunciations WHERE noun_id = ?"; | ||
1023 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
1024 | { | ||
1025 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
1026 | } | ||
1027 | |||
1028 | sqlite3_bind_int(ppstmt, 1, noun._id); | ||
1029 | |||
1030 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
1031 | { | ||
1032 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
1033 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
1034 | |||
1035 | noun.pronunciations.push_back(phonemes); | ||
1036 | } | ||
1037 | |||
1038 | sqlite3_finalize(ppstmt); | ||
1039 | } | ||
1040 | |||
1041 | return output; | ||
1042 | } | 160 | } |
1043 | 161 | ||
1044 | }; | 162 | }; |
diff --git a/lib/noun.h b/lib/noun.h index fbc2f9e..77601d0 100644 --- a/lib/noun.h +++ b/lib/noun.h | |||
@@ -11,6 +11,7 @@ namespace verbly { | |||
11 | friend class noun_query; | 11 | friend class noun_query; |
12 | 12 | ||
13 | public: | 13 | public: |
14 | noun(); | ||
14 | noun(const data& _data, int _id); | 15 | noun(const data& _data, int _id); |
15 | 16 | ||
16 | std::string base_form() const; | 17 | std::string base_form() const; |
@@ -20,7 +21,9 @@ namespace verbly { | |||
20 | bool has_plural_form() const; | 21 | bool has_plural_form() const; |
21 | 22 | ||
22 | noun_query hypernyms() const; | 23 | noun_query hypernyms() const; |
24 | noun_query full_hypernyms() const; | ||
23 | noun_query hyponyms() const; | 25 | noun_query hyponyms() const; |
26 | noun_query full_hyponyms() const; | ||
24 | noun_query part_meronyms() const; | 27 | noun_query part_meronyms() const; |
25 | noun_query part_holonyms() const; | 28 | noun_query part_holonyms() const; |
26 | noun_query substance_meronyms() const; | 29 | noun_query substance_meronyms() const; |
@@ -33,153 +36,8 @@ namespace verbly { | |||
33 | noun_query antonyms() const; | 36 | noun_query antonyms() const; |
34 | adjective_query pertainyms() const; | 37 | adjective_query pertainyms() const; |
35 | adjective_query variations() const; | 38 | adjective_query variations() const; |
36 | }; | ||
37 | |||
38 | class noun_query { | ||
39 | public: | ||
40 | noun_query(const data& _data); | ||
41 | |||
42 | noun_query& limit(int _limit); | ||
43 | noun_query& random(bool _random); | ||
44 | noun_query& except(const noun& _word); | ||
45 | noun_query& rhymes_with(const word& _word); | ||
46 | noun_query& has_pronunciation(bool _has_prn); | ||
47 | |||
48 | noun_query& is_hypernym(bool _arg); | ||
49 | noun_query& hypernym_of(const noun& _noun); | ||
50 | noun_query& not_hypernym_of(const noun& _noun); | ||
51 | |||
52 | noun_query& is_hyponym(bool _arg); | ||
53 | noun_query& hyponym_of(const noun& _noun); | ||
54 | noun_query& not_hyponym_of(const noun& _noun); | ||
55 | |||
56 | noun_query& is_part_meronym(bool _arg); | ||
57 | noun_query& part_meronym_of(const noun& _noun); | ||
58 | noun_query& not_part_meronym_of(const noun& _noun); | ||
59 | |||
60 | noun_query& is_part_holonym(bool _arg); | ||
61 | noun_query& part_holonym_of(const noun& _noun); | ||
62 | noun_query& not_part_holonym_of(const noun& _noun); | ||
63 | |||
64 | noun_query& is_substance_meronym(bool _arg); | ||
65 | noun_query& substance_meronym_of(const noun& _noun); | ||
66 | noun_query& not_substance_meronym_of(const noun& _noun); | ||
67 | |||
68 | noun_query& is_substance_holonym(bool _arg); | ||
69 | noun_query& substance_holonym_of(const noun& _noun); | ||
70 | noun_query& not_substance_holonym_of(const noun& _noun); | ||
71 | |||
72 | noun_query& is_member_meronym(bool _arg); | ||
73 | noun_query& member_meronym_of(const noun& _noun); | ||
74 | noun_query& not_member_meronym_of(const noun& _noun); | ||
75 | |||
76 | noun_query& is_member_holonym(bool _arg); | ||
77 | noun_query& member_holonym_of(const noun& _noun); | ||
78 | noun_query& not_member_holonym_of(const noun& _noun); | ||
79 | |||
80 | noun_query& is_proper(bool _arg); | ||
81 | noun_query& is_not_proper(bool _arg); | ||
82 | |||
83 | noun_query& is_instance(bool _arg); | ||
84 | noun_query& instance_of(const noun& _noun); | ||
85 | noun_query& not_instance_of(const noun& _noun); | ||
86 | |||
87 | noun_query& is_class(bool _arg); | ||
88 | noun_query& class_of(const noun& _noun); | ||
89 | noun_query& not_class_of(const noun& _noun); | ||
90 | |||
91 | noun_query& has_synonyms(bool _arg); | ||
92 | noun_query& synonym_of(const noun& _noun); | ||
93 | noun_query& not_synonym_of(const noun& _noun); | ||
94 | |||
95 | noun_query& has_antonyms(bool _arg); | ||
96 | noun_query& antonym_of(const noun& _noun); | ||
97 | noun_query& not_antonym_of(const noun& _noun); | ||
98 | |||
99 | noun_query& has_pertainym(bool _arg); | ||
100 | noun_query& anti_pertainym_of(const adjective& _adj); | ||
101 | |||
102 | noun_query& is_attribute(bool _arg); | ||
103 | noun_query& attribute_of(const adjective& _adj); | ||
104 | |||
105 | noun_query& derived_from(const word& _w); | ||
106 | noun_query& not_derived_from(const word& _w); | ||
107 | |||
108 | std::list<noun> run() const; | ||
109 | |||
110 | const static int unlimited = -1; | ||
111 | |||
112 | private: | ||
113 | const data& _data; | ||
114 | int _limit = unlimited; | ||
115 | bool _random = false; | ||
116 | std::list<std::string> _rhymes; | ||
117 | std::list<noun> _except; | ||
118 | bool _has_prn = false; | ||
119 | |||
120 | bool _is_hypernym = false; | ||
121 | std::list<noun> _hypernym_of; | ||
122 | std::list<noun> _not_hypernym_of; | ||
123 | |||
124 | bool _is_hyponym = false; | ||
125 | std::list<noun> _hyponym_of; | ||
126 | std::list<noun> _not_hyponym_of; | ||
127 | |||
128 | bool _is_part_meronym = false; | ||
129 | std::list<noun> _part_meronym_of; | ||
130 | std::list<noun> _not_part_meronym_of; | ||
131 | |||
132 | bool _is_substance_meronym = false; | ||
133 | std::list<noun> _substance_meronym_of; | ||
134 | std::list<noun> _not_substance_meronym_of; | ||
135 | |||
136 | bool _is_member_meronym = false; | ||
137 | std::list<noun> _member_meronym_of; | ||
138 | std::list<noun> _not_member_meronym_of; | ||
139 | |||
140 | bool _is_part_holonym = false; | ||
141 | std::list<noun> _part_holonym_of; | ||
142 | std::list<noun> _not_part_holonym_of; | ||
143 | |||
144 | bool _is_substance_holonym = false; | ||
145 | std::list<noun> _substance_holonym_of; | ||
146 | std::list<noun> _not_substance_holonym_of; | ||
147 | |||
148 | bool _is_member_holonym = false; | ||
149 | std::list<noun> _member_holonym_of; | ||
150 | std::list<noun> _not_member_holonym_of; | ||
151 | |||
152 | bool _is_proper = false; | ||
153 | bool _is_not_proper = false; | ||
154 | |||
155 | bool _is_instance = false; | ||
156 | std::list<noun> _instance_of; | ||
157 | std::list<noun> _not_instance_of; | ||
158 | |||
159 | bool _is_class = false; | ||
160 | std::list<noun> _class_of; | ||
161 | std::list<noun> _not_class_of; | ||
162 | |||
163 | bool _has_synonyms = false; | ||
164 | std::list<noun> _synonym_of; | ||
165 | std::list<noun> _not_synonym_of; | ||
166 | |||
167 | bool _has_antonyms = false; | ||
168 | std::list<noun> _antonym_of; | ||
169 | std::list<noun> _not_antonym_of; | ||
170 | |||
171 | bool _has_pertainym = false; | ||
172 | std::list<adjective> _anti_pertainym_of; | ||
173 | |||
174 | bool _is_attribute = false; | ||
175 | std::list<adjective> _attribute_of; | ||
176 | 39 | ||
177 | std::list<adjective> _derived_from_adjective; | 40 | bool operator<(const noun& other) const; |
178 | std::list<adjective> _not_derived_from_adjective; | ||
179 | std::list<adverb> _derived_from_adverb; | ||
180 | std::list<adverb> _not_derived_from_adverb; | ||
181 | std::list<noun> _derived_from_noun; | ||
182 | std::list<noun> _not_derived_from_noun; | ||
183 | }; | 41 | }; |
184 | 42 | ||
185 | }; | 43 | }; |
diff --git a/lib/noun_query.cpp b/lib/noun_query.cpp new file mode 100644 index 0000000..cb11577 --- /dev/null +++ b/lib/noun_query.cpp | |||
@@ -0,0 +1,1453 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | noun_query::noun_query(const data& _data) : _data(_data) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | noun_query& noun_query::limit(int _limit) | ||
11 | { | ||
12 | if ((_limit > 0) || (_limit == unlimited)) | ||
13 | { | ||
14 | this->_limit = _limit; | ||
15 | } | ||
16 | |||
17 | return *this; | ||
18 | } | ||
19 | |||
20 | noun_query& noun_query::random() | ||
21 | { | ||
22 | this->_random = true; | ||
23 | |||
24 | return *this; | ||
25 | } | ||
26 | |||
27 | noun_query& noun_query::except(const noun& _word) | ||
28 | { | ||
29 | _except.push_back(_word); | ||
30 | |||
31 | return *this; | ||
32 | } | ||
33 | |||
34 | noun_query& noun_query::rhymes_with(const word& _word) | ||
35 | { | ||
36 | for (auto rhyme : _word.rhyme_phonemes()) | ||
37 | { | ||
38 | _rhymes.push_back(rhyme); | ||
39 | } | ||
40 | |||
41 | if (dynamic_cast<const noun*>(&_word) != nullptr) | ||
42 | { | ||
43 | _except.push_back(dynamic_cast<const noun&>(_word)); | ||
44 | } | ||
45 | |||
46 | return *this; | ||
47 | } | ||
48 | |||
49 | noun_query& noun_query::has_pronunciation() | ||
50 | { | ||
51 | this->_has_prn = true; | ||
52 | |||
53 | return *this; | ||
54 | } | ||
55 | |||
56 | noun_query& noun_query::with_singular_form(std::string _arg) | ||
57 | { | ||
58 | _with_singular_form.push_back(_arg); | ||
59 | |||
60 | return *this; | ||
61 | } | ||
62 | |||
63 | noun_query& noun_query::is_hypernym() | ||
64 | { | ||
65 | _is_hypernym = true; | ||
66 | |||
67 | return *this; | ||
68 | } | ||
69 | |||
70 | noun_query& noun_query::hypernym_of(filter<noun> _f) | ||
71 | { | ||
72 | _f.clean(); | ||
73 | _hypernym_of = _f; | ||
74 | |||
75 | return *this; | ||
76 | } | ||
77 | |||
78 | noun_query& noun_query::full_hypernym_of(filter<noun> _f) | ||
79 | { | ||
80 | _f.clean(); | ||
81 | _full_hypernym_of = _f; | ||
82 | |||
83 | return *this; | ||
84 | } | ||
85 | |||
86 | noun_query& noun_query::is_hyponym() | ||
87 | { | ||
88 | _is_hyponym = true; | ||
89 | |||
90 | return *this; | ||
91 | } | ||
92 | |||
93 | noun_query& noun_query::hyponym_of(filter<noun> _f) | ||
94 | { | ||
95 | _f.clean(); | ||
96 | _hyponym_of = _f; | ||
97 | |||
98 | return *this; | ||
99 | } | ||
100 | |||
101 | noun_query& noun_query::full_hyponym_of(filter<noun> _f) | ||
102 | { | ||
103 | _f.clean(); | ||
104 | _full_hyponym_of = _f; | ||
105 | |||
106 | return *this; | ||
107 | } | ||
108 | |||
109 | noun_query& noun_query::is_part_meronym() | ||
110 | { | ||
111 | _is_part_meronym = true; | ||
112 | |||
113 | return *this; | ||
114 | } | ||
115 | |||
116 | noun_query& noun_query::part_meronym_of(filter<noun> _f) | ||
117 | { | ||
118 | _f.clean(); | ||
119 | _part_meronym_of = _f; | ||
120 | |||
121 | return *this; | ||
122 | } | ||
123 | |||
124 | noun_query& noun_query::is_part_holonym() | ||
125 | { | ||
126 | _is_part_holonym = true; | ||
127 | |||
128 | return *this; | ||
129 | } | ||
130 | |||
131 | noun_query& noun_query::part_holonym_of(filter<noun> _f) | ||
132 | { | ||
133 | _f.clean(); | ||
134 | _part_holonym_of = _f; | ||
135 | |||
136 | return *this; | ||
137 | } | ||
138 | |||
139 | noun_query& noun_query::is_substance_meronym() | ||
140 | { | ||
141 | _is_substance_meronym = true; | ||
142 | |||
143 | return *this; | ||
144 | } | ||
145 | |||
146 | noun_query& noun_query::substance_meronym_of(filter<noun> _f) | ||
147 | { | ||
148 | _f.clean(); | ||
149 | _substance_meronym_of = _f; | ||
150 | |||
151 | return *this; | ||
152 | } | ||
153 | |||
154 | noun_query& noun_query::is_substance_holonym() | ||
155 | { | ||
156 | _is_substance_holonym = true; | ||
157 | |||
158 | return *this; | ||
159 | } | ||
160 | |||
161 | noun_query& noun_query::substance_holonym_of(filter<noun> _f) | ||
162 | { | ||
163 | _f.clean(); | ||
164 | _substance_holonym_of = _f; | ||
165 | |||
166 | return *this; | ||
167 | } | ||
168 | |||
169 | noun_query& noun_query::is_member_meronym() | ||
170 | { | ||
171 | _is_member_meronym = true; | ||
172 | |||
173 | return *this; | ||
174 | } | ||
175 | |||
176 | noun_query& noun_query::member_meronym_of(filter<noun> _f) | ||
177 | { | ||
178 | _f.clean(); | ||
179 | _member_meronym_of = _f; | ||
180 | |||
181 | return *this; | ||
182 | } | ||
183 | |||
184 | noun_query& noun_query::is_member_holonym() | ||
185 | { | ||
186 | _is_member_holonym = true; | ||
187 | |||
188 | return *this; | ||
189 | } | ||
190 | |||
191 | noun_query& noun_query::member_holonym_of(filter<noun> _f) | ||
192 | { | ||
193 | _f.clean(); | ||
194 | _member_holonym_of = _f; | ||
195 | |||
196 | return *this; | ||
197 | } | ||
198 | |||
199 | noun_query& noun_query::is_proper() | ||
200 | { | ||
201 | _is_proper = true; | ||
202 | |||
203 | return *this; | ||
204 | } | ||
205 | |||
206 | noun_query& noun_query::is_not_proper() | ||
207 | { | ||
208 | _is_not_proper = true; | ||
209 | |||
210 | return *this; | ||
211 | } | ||
212 | |||
213 | noun_query& noun_query::is_instance() | ||
214 | { | ||
215 | _is_instance = true; | ||
216 | |||
217 | return *this; | ||
218 | } | ||
219 | |||
220 | noun_query& noun_query::instance_of(filter<noun> _f) | ||
221 | { | ||
222 | _f.clean(); | ||
223 | _instance_of = _f; | ||
224 | |||
225 | return *this; | ||
226 | } | ||
227 | |||
228 | noun_query& noun_query::is_class() | ||
229 | { | ||
230 | _is_class = true; | ||
231 | |||
232 | return *this; | ||
233 | } | ||
234 | |||
235 | noun_query& noun_query::class_of(filter<noun> _f) | ||
236 | { | ||
237 | _f.clean(); | ||
238 | _class_of = _f; | ||
239 | |||
240 | return *this; | ||
241 | } | ||
242 | |||
243 | noun_query& noun_query::has_synonyms() | ||
244 | { | ||
245 | _has_synonyms = true; | ||
246 | |||
247 | return *this; | ||
248 | } | ||
249 | |||
250 | noun_query& noun_query::synonym_of(filter<noun> _f) | ||
251 | { | ||
252 | _f.clean(); | ||
253 | _synonym_of = _f; | ||
254 | |||
255 | return *this; | ||
256 | } | ||
257 | |||
258 | noun_query& noun_query::has_antonyms() | ||
259 | { | ||
260 | _has_antonyms = true; | ||
261 | |||
262 | return *this; | ||
263 | } | ||
264 | |||
265 | noun_query& noun_query::antonym_of(filter<noun> _f) | ||
266 | { | ||
267 | _f.clean(); | ||
268 | _antonym_of = _f; | ||
269 | |||
270 | return *this; | ||
271 | } | ||
272 | |||
273 | noun_query& noun_query::has_pertainym() | ||
274 | { | ||
275 | _has_pertainym = true; | ||
276 | |||
277 | return *this; | ||
278 | } | ||
279 | |||
280 | noun_query& noun_query::anti_pertainym_of(filter<adjective> _f) | ||
281 | { | ||
282 | _f.clean(); | ||
283 | _anti_pertainym_of = _f; | ||
284 | |||
285 | return *this; | ||
286 | } | ||
287 | |||
288 | noun_query& noun_query::is_attribute() | ||
289 | { | ||
290 | _is_attribute = true; | ||
291 | |||
292 | return *this; | ||
293 | } | ||
294 | |||
295 | noun_query& noun_query::attribute_of(filter<adjective> _f) | ||
296 | { | ||
297 | _f.clean(); | ||
298 | _attribute_of = _f; | ||
299 | |||
300 | return *this; | ||
301 | } | ||
302 | /* | ||
303 | noun_query& noun_query::derived_from(const word& _w) | ||
304 | { | ||
305 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
306 | { | ||
307 | _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
308 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
309 | { | ||
310 | _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
311 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
312 | { | ||
313 | _derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
314 | } | ||
315 | |||
316 | return *this; | ||
317 | } | ||
318 | |||
319 | noun_query& noun_query::not_derived_from(const word& _w) | ||
320 | { | ||
321 | if (dynamic_cast<const adjective*>(&_w) != nullptr) | ||
322 | { | ||
323 | _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w)); | ||
324 | } else if (dynamic_cast<const adverb*>(&_w) != nullptr) | ||
325 | { | ||
326 | _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w)); | ||
327 | } else if (dynamic_cast<const noun*>(&_w) != nullptr) | ||
328 | { | ||
329 | _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w)); | ||
330 | } | ||
331 | |||
332 | return *this; | ||
333 | }*/ | ||
334 | |||
335 | std::list<noun> noun_query::run() const | ||
336 | { | ||
337 | std::stringstream construct; | ||
338 | |||
339 | if (!_full_hypernym_of.empty() || !_full_hyponym_of.empty()) | ||
340 | { | ||
341 | construct << "WITH RECURSIVE "; | ||
342 | |||
343 | std::list<std::string> ctes; | ||
344 | |||
345 | for (auto hyponym : _full_hypernym_of.uniq_flatten()) | ||
346 | { | ||
347 | ctes.push_back("hypernym_tree_" + std::to_string(hyponym._id) + " AS (SELECT hypernym_id FROM hypernymy WHERE hyponym_id = " + std::to_string(hyponym._id) + " UNION SELECT h.hypernym_id FROM hypernym_tree_" + std::to_string(hyponym._id) + " AS t INNER JOIN hypernymy AS h ON t.hypernym_id = h.hyponym_id)"); | ||
348 | } | ||
349 | |||
350 | for (auto hypernym : _full_hyponym_of.uniq_flatten()) | ||
351 | { | ||
352 | ctes.push_back("hyponym_tree_" + std::to_string(hypernym._id) + " AS (SELECT hyponym_id FROM hypernymy WHERE hypernym_id = " + std::to_string(hypernym._id) + " UNION SELECT h.hyponym_id FROM hyponym_tree_" + std::to_string(hypernym._id) + " AS t INNER JOIN hypernymy AS h ON t.hyponym_id = h.hypernym_id)"); | ||
353 | } | ||
354 | |||
355 | construct << verbly::implode(std::begin(ctes), std::end(ctes), ", "); | ||
356 | construct << " "; | ||
357 | } | ||
358 | |||
359 | construct << "SELECT noun_id, singular, plural FROM nouns"; | ||
360 | std::list<std::string> conditions; | ||
361 | |||
362 | if (_has_prn) | ||
363 | { | ||
364 | conditions.push_back("noun_id IN (SELECT noun_id FROM noun_pronunciations)"); | ||
365 | } | ||
366 | |||
367 | if (!_rhymes.empty()) | ||
368 | { | ||
369 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
370 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
371 | conditions.push_back(cond); | ||
372 | } | ||
373 | |||
374 | for (auto except : _except) | ||
375 | { | ||
376 | conditions.push_back("noun_id != @EXCID"); | ||
377 | } | ||
378 | |||
379 | if (!_with_singular_form.empty()) | ||
380 | { | ||
381 | std::list<std::string> clauses(_with_singular_form.size(), "singular = @SFORM"); | ||
382 | std::string cond = "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
383 | conditions.push_back(cond); | ||
384 | } | ||
385 | |||
386 | if (_is_hypernym) | ||
387 | { | ||
388 | conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)"); | ||
389 | } | ||
390 | |||
391 | if (!_hypernym_of.empty()) | ||
392 | { | ||
393 | std::stringstream cond; | ||
394 | if (_hypernym_of.get_notlogic()) | ||
395 | { | ||
396 | cond << "noun_id NOT IN"; | ||
397 | } else { | ||
398 | cond << "noun_id IN"; | ||
399 | } | ||
400 | |||
401 | cond << "(SELECT hypernym_id FROM hypernymy WHERE "; | ||
402 | |||
403 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
404 | switch (f.get_type()) | ||
405 | { | ||
406 | case filter<noun>::type::singleton: | ||
407 | { | ||
408 | if (notlogic == f.get_notlogic()) | ||
409 | { | ||
410 | return "hyponym_id = @HYPO"; | ||
411 | } else { | ||
412 | return "hyponym_id != @HYPO"; | ||
413 | } | ||
414 | } | ||
415 | |||
416 | case filter<noun>::type::group: | ||
417 | { | ||
418 | bool truelogic = notlogic != f.get_notlogic(); | ||
419 | |||
420 | std::list<std::string> clauses; | ||
421 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
422 | return recur(f2, truelogic); | ||
423 | }); | ||
424 | |||
425 | if (truelogic == f.get_orlogic()) | ||
426 | { | ||
427 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
428 | } else { | ||
429 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | }; | ||
434 | |||
435 | cond << recur(_hypernym_of, _hypernym_of.get_notlogic()); | ||
436 | cond << ")"; | ||
437 | conditions.push_back(cond.str()); | ||
438 | } | ||
439 | |||
440 | if (!_full_hypernym_of.empty()) | ||
441 | { | ||
442 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
443 | switch (f.get_type()) | ||
444 | { | ||
445 | case filter<noun>::type::singleton: | ||
446 | { | ||
447 | if (notlogic == f.get_notlogic()) | ||
448 | { | ||
449 | return "noun_id IN (SELECT hypernym_id FROM hypernym_tree_" + std::to_string(f.get_elem()._id) + ")"; | ||
450 | } else { | ||
451 | return "noun_id NOT IN (SELECT hypernym_id FROM hypernym_tree_" + std::to_string(f.get_elem()._id) + ")"; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | case filter<noun>::type::group: | ||
456 | { | ||
457 | bool truelogic = notlogic != f.get_notlogic(); | ||
458 | |||
459 | std::list<std::string> clauses; | ||
460 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
461 | return recur(f2, truelogic); | ||
462 | }); | ||
463 | |||
464 | if (truelogic == f.get_orlogic()) | ||
465 | { | ||
466 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
467 | } else { | ||
468 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | }; | ||
473 | |||
474 | conditions.push_back(recur(_full_hypernym_of, false)); | ||
475 | } | ||
476 | |||
477 | if (!_full_hyponym_of.empty()) | ||
478 | { | ||
479 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
480 | switch (f.get_type()) | ||
481 | { | ||
482 | case filter<noun>::type::singleton: | ||
483 | { | ||
484 | if (notlogic == f.get_notlogic()) | ||
485 | { | ||
486 | return "noun_id IN (SELECT hyponym_id FROM hyponym_tree_" + std::to_string(f.get_elem()._id) + ")"; | ||
487 | } else { | ||
488 | return "noun_id NOT IN (SELECT hyponym_id FROM hyponym_tree_" + std::to_string(f.get_elem()._id) + ")"; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | case filter<noun>::type::group: | ||
493 | { | ||
494 | bool truelogic = notlogic != f.get_notlogic(); | ||
495 | |||
496 | std::list<std::string> clauses; | ||
497 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
498 | return recur(f2, truelogic); | ||
499 | }); | ||
500 | |||
501 | if (truelogic == f.get_orlogic()) | ||
502 | { | ||
503 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
504 | } else { | ||
505 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
506 | } | ||
507 | } | ||
508 | } | ||
509 | }; | ||
510 | |||
511 | conditions.push_back(recur(_full_hyponym_of, false)); | ||
512 | } | ||
513 | |||
514 | if (_is_hyponym) | ||
515 | { | ||
516 | conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)"); | ||
517 | } | ||
518 | |||
519 | if (!_hyponym_of.empty()) | ||
520 | { | ||
521 | std::stringstream cond; | ||
522 | if (_hyponym_of.get_notlogic()) | ||
523 | { | ||
524 | cond << "noun_id NOT IN"; | ||
525 | } else { | ||
526 | cond << "noun_id IN"; | ||
527 | } | ||
528 | |||
529 | cond << "(SELECT hyponym_id FROM hypernymy WHERE "; | ||
530 | |||
531 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
532 | switch (f.get_type()) | ||
533 | { | ||
534 | case filter<noun>::type::singleton: | ||
535 | { | ||
536 | if (notlogic == f.get_notlogic()) | ||
537 | { | ||
538 | return "hypernym_id = @HYPER"; | ||
539 | } else { | ||
540 | return "hypernym_id != @HYPER"; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | case filter<noun>::type::group: | ||
545 | { | ||
546 | bool truelogic = notlogic != f.get_notlogic(); | ||
547 | |||
548 | std::list<std::string> clauses; | ||
549 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
550 | return recur(f2, truelogic); | ||
551 | }); | ||
552 | |||
553 | if (truelogic == f.get_orlogic()) | ||
554 | { | ||
555 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
556 | } else { | ||
557 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
558 | } | ||
559 | } | ||
560 | } | ||
561 | }; | ||
562 | |||
563 | cond << recur(_hyponym_of, _hyponym_of.get_notlogic()); | ||
564 | cond << ")"; | ||
565 | conditions.push_back(cond.str()); | ||
566 | } | ||
567 | |||
568 | if (_is_part_meronym) | ||
569 | { | ||
570 | conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)"); | ||
571 | } | ||
572 | |||
573 | if (!_part_meronym_of.empty()) | ||
574 | { | ||
575 | std::stringstream cond; | ||
576 | if (_part_meronym_of.get_notlogic()) | ||
577 | { | ||
578 | cond << "noun_id NOT IN"; | ||
579 | } else { | ||
580 | cond << "noun_id IN"; | ||
581 | } | ||
582 | |||
583 | cond << "(SELECT meronym_id FROM part_meronymy WHERE "; | ||
584 | |||
585 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
586 | switch (f.get_type()) | ||
587 | { | ||
588 | case filter<noun>::type::singleton: | ||
589 | { | ||
590 | if (notlogic == f.get_notlogic()) | ||
591 | { | ||
592 | return "holonym_id = @PHOLO"; | ||
593 | } else { | ||
594 | return "holonym_id != @PHOLO"; | ||
595 | } | ||
596 | } | ||
597 | |||
598 | case filter<noun>::type::group: | ||
599 | { | ||
600 | bool truelogic = notlogic != f.get_notlogic(); | ||
601 | |||
602 | std::list<std::string> clauses; | ||
603 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
604 | return recur(f2, truelogic); | ||
605 | }); | ||
606 | |||
607 | if (truelogic == f.get_orlogic()) | ||
608 | { | ||
609 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
610 | } else { | ||
611 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
612 | } | ||
613 | } | ||
614 | } | ||
615 | }; | ||
616 | |||
617 | cond << recur(_part_meronym_of, _part_meronym_of.get_notlogic()); | ||
618 | cond << ")"; | ||
619 | conditions.push_back(cond.str()); | ||
620 | } | ||
621 | |||
622 | if (_is_part_holonym) | ||
623 | { | ||
624 | conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)"); | ||
625 | } | ||
626 | |||
627 | if (!_part_holonym_of.empty()) | ||
628 | { | ||
629 | std::stringstream cond; | ||
630 | if (_part_holonym_of.get_notlogic()) | ||
631 | { | ||
632 | cond << "noun_id NOT IN"; | ||
633 | } else { | ||
634 | cond << "noun_id IN"; | ||
635 | } | ||
636 | |||
637 | cond << "(SELECT holonym_id FROM part_meronymy WHERE "; | ||
638 | |||
639 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
640 | switch (f.get_type()) | ||
641 | { | ||
642 | case filter<noun>::type::singleton: | ||
643 | { | ||
644 | if (notlogic == f.get_notlogic()) | ||
645 | { | ||
646 | return "meronym_id = @PMERO"; | ||
647 | } else { | ||
648 | return "meronym_id != @PMERO"; | ||
649 | } | ||
650 | } | ||
651 | |||
652 | case filter<noun>::type::group: | ||
653 | { | ||
654 | bool truelogic = notlogic != f.get_notlogic(); | ||
655 | |||
656 | std::list<std::string> clauses; | ||
657 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
658 | return recur(f2, truelogic); | ||
659 | }); | ||
660 | |||
661 | if (truelogic == f.get_orlogic()) | ||
662 | { | ||
663 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
664 | } else { | ||
665 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | }; | ||
670 | |||
671 | cond << recur(_part_holonym_of, _part_holonym_of.get_notlogic()); | ||
672 | cond << ")"; | ||
673 | conditions.push_back(cond.str()); | ||
674 | } | ||
675 | |||
676 | if (_is_substance_meronym) | ||
677 | { | ||
678 | conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)"); | ||
679 | } | ||
680 | |||
681 | if (!_substance_meronym_of.empty()) | ||
682 | { | ||
683 | std::stringstream cond; | ||
684 | if (_substance_meronym_of.get_notlogic()) | ||
685 | { | ||
686 | cond << "noun_id NOT IN"; | ||
687 | } else { | ||
688 | cond << "noun_id IN"; | ||
689 | } | ||
690 | |||
691 | cond << "(SELECT meronym_id FROM substance_meronymy WHERE "; | ||
692 | |||
693 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
694 | switch (f.get_type()) | ||
695 | { | ||
696 | case filter<noun>::type::singleton: | ||
697 | { | ||
698 | if (notlogic == f.get_notlogic()) | ||
699 | { | ||
700 | return "holonym_id = @SHOLO"; | ||
701 | } else { | ||
702 | return "holonym_id != @SHOLO"; | ||
703 | } | ||
704 | } | ||
705 | |||
706 | case filter<noun>::type::group: | ||
707 | { | ||
708 | bool truelogic = notlogic != f.get_notlogic(); | ||
709 | |||
710 | std::list<std::string> clauses; | ||
711 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
712 | return recur(f2, truelogic); | ||
713 | }); | ||
714 | |||
715 | if (truelogic == f.get_orlogic()) | ||
716 | { | ||
717 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
718 | } else { | ||
719 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
720 | } | ||
721 | } | ||
722 | } | ||
723 | }; | ||
724 | |||
725 | cond << recur(_substance_meronym_of, _substance_meronym_of.get_notlogic()); | ||
726 | cond << ")"; | ||
727 | conditions.push_back(cond.str()); | ||
728 | } | ||
729 | |||
730 | if (_is_substance_holonym) | ||
731 | { | ||
732 | conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)"); | ||
733 | } | ||
734 | |||
735 | if (!_substance_holonym_of.empty()) | ||
736 | { | ||
737 | std::stringstream cond; | ||
738 | if (_substance_holonym_of.get_notlogic()) | ||
739 | { | ||
740 | cond << "noun_id NOT IN"; | ||
741 | } else { | ||
742 | cond << "noun_id IN"; | ||
743 | } | ||
744 | |||
745 | cond << "(SELECT holonym_id FROM substance_meronymy WHERE "; | ||
746 | |||
747 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
748 | switch (f.get_type()) | ||
749 | { | ||
750 | case filter<noun>::type::singleton: | ||
751 | { | ||
752 | if (notlogic == f.get_notlogic()) | ||
753 | { | ||
754 | return "meronym_id = @SMERO"; | ||
755 | } else { | ||
756 | return "meronym_id != @SMERO"; | ||
757 | } | ||
758 | } | ||
759 | |||
760 | case filter<noun>::type::group: | ||
761 | { | ||
762 | bool truelogic = notlogic != f.get_notlogic(); | ||
763 | |||
764 | std::list<std::string> clauses; | ||
765 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
766 | return recur(f2, truelogic); | ||
767 | }); | ||
768 | |||
769 | if (truelogic == f.get_orlogic()) | ||
770 | { | ||
771 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
772 | } else { | ||
773 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
774 | } | ||
775 | } | ||
776 | } | ||
777 | }; | ||
778 | |||
779 | cond << recur(_substance_holonym_of, _substance_holonym_of.get_notlogic()); | ||
780 | cond << ")"; | ||
781 | conditions.push_back(cond.str()); | ||
782 | } | ||
783 | |||
784 | if (_is_member_meronym) | ||
785 | { | ||
786 | conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)"); | ||
787 | } | ||
788 | |||
789 | if (!_member_meronym_of.empty()) | ||
790 | { | ||
791 | std::stringstream cond; | ||
792 | if (_member_meronym_of.get_notlogic()) | ||
793 | { | ||
794 | cond << "noun_id NOT IN"; | ||
795 | } else { | ||
796 | cond << "noun_id IN"; | ||
797 | } | ||
798 | |||
799 | cond << "(SELECT meronym_id FROM member_meronymy WHERE "; | ||
800 | |||
801 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
802 | switch (f.get_type()) | ||
803 | { | ||
804 | case filter<noun>::type::singleton: | ||
805 | { | ||
806 | if (notlogic == f.get_notlogic()) | ||
807 | { | ||
808 | return "holonym_id = @MHOLO"; | ||
809 | } else { | ||
810 | return "holonym_id != @MHOLO"; | ||
811 | } | ||
812 | } | ||
813 | |||
814 | case filter<noun>::type::group: | ||
815 | { | ||
816 | bool truelogic = notlogic != f.get_notlogic(); | ||
817 | |||
818 | std::list<std::string> clauses; | ||
819 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
820 | return recur(f2, truelogic); | ||
821 | }); | ||
822 | |||
823 | if (truelogic == f.get_orlogic()) | ||
824 | { | ||
825 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
826 | } else { | ||
827 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
828 | } | ||
829 | } | ||
830 | } | ||
831 | }; | ||
832 | |||
833 | cond << recur(_member_meronym_of, _member_meronym_of.get_notlogic()); | ||
834 | cond << ")"; | ||
835 | conditions.push_back(cond.str()); | ||
836 | } | ||
837 | |||
838 | if (_is_member_holonym) | ||
839 | { | ||
840 | conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)"); | ||
841 | } | ||
842 | |||
843 | if (!_member_holonym_of.empty()) | ||
844 | { | ||
845 | std::stringstream cond; | ||
846 | if (_member_holonym_of.get_notlogic()) | ||
847 | { | ||
848 | cond << "noun_id NOT IN"; | ||
849 | } else { | ||
850 | cond << "noun_id IN"; | ||
851 | } | ||
852 | |||
853 | cond << "(SELECT holonym_id FROM member_meronymy WHERE "; | ||
854 | |||
855 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
856 | switch (f.get_type()) | ||
857 | { | ||
858 | case filter<noun>::type::singleton: | ||
859 | { | ||
860 | if (notlogic == f.get_notlogic()) | ||
861 | { | ||
862 | return "meronym_id = @MMERO"; | ||
863 | } else { | ||
864 | return "meronym_id != @MMERO"; | ||
865 | } | ||
866 | } | ||
867 | |||
868 | case filter<noun>::type::group: | ||
869 | { | ||
870 | bool truelogic = notlogic != f.get_notlogic(); | ||
871 | |||
872 | std::list<std::string> clauses; | ||
873 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
874 | return recur(f2, truelogic); | ||
875 | }); | ||
876 | |||
877 | if (truelogic == f.get_orlogic()) | ||
878 | { | ||
879 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
880 | } else { | ||
881 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
882 | } | ||
883 | } | ||
884 | } | ||
885 | }; | ||
886 | |||
887 | cond << recur(_member_holonym_of, _member_holonym_of.get_notlogic()); | ||
888 | cond << ")"; | ||
889 | conditions.push_back(cond.str()); | ||
890 | } | ||
891 | |||
892 | if (_is_proper) | ||
893 | { | ||
894 | conditions.push_back("proper = 1"); | ||
895 | } | ||
896 | |||
897 | if (_is_not_proper) | ||
898 | { | ||
899 | conditions.push_back("proper = 0"); | ||
900 | } | ||
901 | |||
902 | if (_is_instance) | ||
903 | { | ||
904 | conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)"); | ||
905 | } | ||
906 | |||
907 | if (!_instance_of.empty()) | ||
908 | { | ||
909 | std::stringstream cond; | ||
910 | if (_instance_of.get_notlogic()) | ||
911 | { | ||
912 | cond << "noun_id NOT IN"; | ||
913 | } else { | ||
914 | cond << "noun_id IN"; | ||
915 | } | ||
916 | |||
917 | cond << "(SELECT instance_id FROM instantiation WHERE "; | ||
918 | |||
919 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
920 | switch (f.get_type()) | ||
921 | { | ||
922 | case filter<noun>::type::singleton: | ||
923 | { | ||
924 | if (notlogic == f.get_notlogic()) | ||
925 | { | ||
926 | return "class_id = @CLSID"; | ||
927 | } else { | ||
928 | return "class_id != @CLSID"; | ||
929 | } | ||
930 | } | ||
931 | |||
932 | case filter<noun>::type::group: | ||
933 | { | ||
934 | bool truelogic = notlogic != f.get_notlogic(); | ||
935 | |||
936 | std::list<std::string> clauses; | ||
937 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
938 | return recur(f2, truelogic); | ||
939 | }); | ||
940 | |||
941 | if (truelogic == f.get_orlogic()) | ||
942 | { | ||
943 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
944 | } else { | ||
945 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
946 | } | ||
947 | } | ||
948 | } | ||
949 | }; | ||
950 | |||
951 | cond << recur(_instance_of, _instance_of.get_notlogic()); | ||
952 | cond << ")"; | ||
953 | conditions.push_back(cond.str()); | ||
954 | } | ||
955 | |||
956 | if (_is_class) | ||
957 | { | ||
958 | conditions.push_back("noun_id IN (SELECT class_id FROM instantiation)"); | ||
959 | } | ||
960 | |||
961 | if (!_class_of.empty()) | ||
962 | { | ||
963 | std::stringstream cond; | ||
964 | if (_class_of.get_notlogic()) | ||
965 | { | ||
966 | cond << "noun_id NOT IN"; | ||
967 | } else { | ||
968 | cond << "noun_id IN"; | ||
969 | } | ||
970 | |||
971 | cond << "(SELECT class_id FROM instantiation WHERE "; | ||
972 | |||
973 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
974 | switch (f.get_type()) | ||
975 | { | ||
976 | case filter<noun>::type::singleton: | ||
977 | { | ||
978 | if (notlogic == f.get_notlogic()) | ||
979 | { | ||
980 | return "instance_id = @INSID"; | ||
981 | } else { | ||
982 | return "instance_id != @INSID"; | ||
983 | } | ||
984 | } | ||
985 | |||
986 | case filter<noun>::type::group: | ||
987 | { | ||
988 | bool truelogic = notlogic != f.get_notlogic(); | ||
989 | |||
990 | std::list<std::string> clauses; | ||
991 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
992 | return recur(f2, truelogic); | ||
993 | }); | ||
994 | |||
995 | if (truelogic == f.get_orlogic()) | ||
996 | { | ||
997 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
998 | } else { | ||
999 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1000 | } | ||
1001 | } | ||
1002 | } | ||
1003 | }; | ||
1004 | |||
1005 | cond << recur(_class_of, _class_of.get_notlogic()); | ||
1006 | cond << ")"; | ||
1007 | conditions.push_back(cond.str()); | ||
1008 | } | ||
1009 | |||
1010 | if (_has_synonyms) | ||
1011 | { | ||
1012 | conditions.push_back("noun_id IN (SELECT noun_2_id FROM noun_synonymy)"); | ||
1013 | } | ||
1014 | |||
1015 | if (!_synonym_of.empty()) | ||
1016 | { | ||
1017 | std::stringstream cond; | ||
1018 | if (_synonym_of.get_notlogic()) | ||
1019 | { | ||
1020 | cond << "noun_id NOT IN"; | ||
1021 | } else { | ||
1022 | cond << "noun_id IN"; | ||
1023 | } | ||
1024 | |||
1025 | cond << "(SELECT noun_2_id FROM noun_synonymy WHERE "; | ||
1026 | |||
1027 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
1028 | switch (f.get_type()) | ||
1029 | { | ||
1030 | case filter<noun>::type::singleton: | ||
1031 | { | ||
1032 | if (notlogic == f.get_notlogic()) | ||
1033 | { | ||
1034 | return "noun_1_id = @SYNID"; | ||
1035 | } else { | ||
1036 | return "noun_1_id != @SYNID"; | ||
1037 | } | ||
1038 | } | ||
1039 | |||
1040 | case filter<noun>::type::group: | ||
1041 | { | ||
1042 | bool truelogic = notlogic != f.get_notlogic(); | ||
1043 | |||
1044 | std::list<std::string> clauses; | ||
1045 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
1046 | return recur(f2, truelogic); | ||
1047 | }); | ||
1048 | |||
1049 | if (truelogic == f.get_orlogic()) | ||
1050 | { | ||
1051 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
1052 | } else { | ||
1053 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1054 | } | ||
1055 | } | ||
1056 | } | ||
1057 | }; | ||
1058 | |||
1059 | cond << recur(_synonym_of, _synonym_of.get_notlogic()); | ||
1060 | cond << ")"; | ||
1061 | conditions.push_back(cond.str()); | ||
1062 | } | ||
1063 | |||
1064 | if (_has_antonyms) | ||
1065 | { | ||
1066 | conditions.push_back("noun_id IN (SELECT noun_2_id FROM noun_antonymy)"); | ||
1067 | } | ||
1068 | |||
1069 | if (!_antonym_of.empty()) | ||
1070 | { | ||
1071 | std::stringstream cond; | ||
1072 | if (_antonym_of.get_notlogic()) | ||
1073 | { | ||
1074 | cond << "noun_id NOT IN"; | ||
1075 | } else { | ||
1076 | cond << "noun_id IN"; | ||
1077 | } | ||
1078 | |||
1079 | cond << "(SELECT noun_2_id FROM noun_antonymy WHERE "; | ||
1080 | |||
1081 | std::function<std::string (filter<noun>, bool)> recur = [&] (filter<noun> f, bool notlogic) -> std::string { | ||
1082 | switch (f.get_type()) | ||
1083 | { | ||
1084 | case filter<noun>::type::singleton: | ||
1085 | { | ||
1086 | if (notlogic == f.get_notlogic()) | ||
1087 | { | ||
1088 | return "noun_1_id = @ANTID"; | ||
1089 | } else { | ||
1090 | return "noun_1_id != @ANTID"; | ||
1091 | } | ||
1092 | } | ||
1093 | |||
1094 | case filter<noun>::type::group: | ||
1095 | { | ||
1096 | bool truelogic = notlogic != f.get_notlogic(); | ||
1097 | |||
1098 | std::list<std::string> clauses; | ||
1099 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<noun> f2) { | ||
1100 | return recur(f2, truelogic); | ||
1101 | }); | ||
1102 | |||
1103 | if (truelogic == f.get_orlogic()) | ||
1104 | { | ||
1105 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
1106 | } else { | ||
1107 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1108 | } | ||
1109 | } | ||
1110 | } | ||
1111 | }; | ||
1112 | |||
1113 | cond << recur(_antonym_of, _antonym_of.get_notlogic()); | ||
1114 | cond << ")"; | ||
1115 | conditions.push_back(cond.str()); | ||
1116 | } | ||
1117 | |||
1118 | if (_has_pertainym) | ||
1119 | { | ||
1120 | conditions.push_back("noun_id IN (SELECT noun_id FROM pertainymy)"); | ||
1121 | } | ||
1122 | |||
1123 | if (!_anti_pertainym_of.empty()) | ||
1124 | { | ||
1125 | std::stringstream cond; | ||
1126 | if (_anti_pertainym_of.get_notlogic()) | ||
1127 | { | ||
1128 | cond << "noun_id NOT IN"; | ||
1129 | } else { | ||
1130 | cond << "noun_id IN"; | ||
1131 | } | ||
1132 | |||
1133 | cond << "(SELECT noun_id FROM pertainymy WHERE "; | ||
1134 | |||
1135 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
1136 | switch (f.get_type()) | ||
1137 | { | ||
1138 | case filter<adjective>::type::singleton: | ||
1139 | { | ||
1140 | if (notlogic == f.get_notlogic()) | ||
1141 | { | ||
1142 | return "pertainym_id = @PERID"; | ||
1143 | } else { | ||
1144 | return "pertainym_id != @PERID"; | ||
1145 | } | ||
1146 | } | ||
1147 | |||
1148 | case filter<adjective>::type::group: | ||
1149 | { | ||
1150 | bool truelogic = notlogic != f.get_notlogic(); | ||
1151 | |||
1152 | std::list<std::string> clauses; | ||
1153 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
1154 | return recur(f2, truelogic); | ||
1155 | }); | ||
1156 | |||
1157 | if (truelogic == f.get_orlogic()) | ||
1158 | { | ||
1159 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
1160 | } else { | ||
1161 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1162 | } | ||
1163 | } | ||
1164 | } | ||
1165 | }; | ||
1166 | |||
1167 | cond << recur(_anti_pertainym_of, _anti_pertainym_of.get_notlogic()); | ||
1168 | cond << ")"; | ||
1169 | conditions.push_back(cond.str()); | ||
1170 | } | ||
1171 | |||
1172 | if (_is_attribute) | ||
1173 | { | ||
1174 | conditions.push_back("noun_id IN (SELECT noun_id FROM variation)"); | ||
1175 | } | ||
1176 | |||
1177 | if (!_attribute_of.empty()) | ||
1178 | { | ||
1179 | std::stringstream cond; | ||
1180 | if (_attribute_of.get_notlogic()) | ||
1181 | { | ||
1182 | cond << "noun_id NOT IN"; | ||
1183 | } else { | ||
1184 | cond << "noun_id IN"; | ||
1185 | } | ||
1186 | |||
1187 | cond << "(SELECT noun_id FROM variation WHERE "; | ||
1188 | |||
1189 | std::function<std::string (filter<adjective>, bool)> recur = [&] (filter<adjective> f, bool notlogic) -> std::string { | ||
1190 | switch (f.get_type()) | ||
1191 | { | ||
1192 | case filter<adjective>::type::singleton: | ||
1193 | { | ||
1194 | if (notlogic == f.get_notlogic()) | ||
1195 | { | ||
1196 | return "adjective_id = @VALID"; | ||
1197 | } else { | ||
1198 | return "adjective_id != @VALID"; | ||
1199 | } | ||
1200 | } | ||
1201 | |||
1202 | case filter<adjective>::type::group: | ||
1203 | { | ||
1204 | bool truelogic = notlogic != f.get_notlogic(); | ||
1205 | |||
1206 | std::list<std::string> clauses; | ||
1207 | std::transform(std::begin(f), std::end(f), std::back_inserter(clauses), [&] (filter<adjective> f2) { | ||
1208 | return recur(f2, truelogic); | ||
1209 | }); | ||
1210 | |||
1211 | if (truelogic == f.get_orlogic()) | ||
1212 | { | ||
1213 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " AND ") + ")"; | ||
1214 | } else { | ||
1215 | return "(" + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1216 | } | ||
1217 | } | ||
1218 | } | ||
1219 | }; | ||
1220 | |||
1221 | cond << recur(_attribute_of, _attribute_of.get_notlogic()); | ||
1222 | cond << ")"; | ||
1223 | conditions.push_back(cond.str()); | ||
1224 | } | ||
1225 | /* | ||
1226 | if (!_derived_from_adjective.empty()) | ||
1227 | { | ||
1228 | std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ"); | ||
1229 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1230 | conditions.push_back(cond); | ||
1231 | } | ||
1232 | |||
1233 | if (!_not_derived_from_adjective.empty()) | ||
1234 | { | ||
1235 | std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ"); | ||
1236 | std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adjective_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1237 | conditions.push_back(cond); | ||
1238 | } | ||
1239 | |||
1240 | if (!_derived_from_adverb.empty()) | ||
1241 | { | ||
1242 | std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_id = @DERADV"); | ||
1243 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1244 | conditions.push_back(cond); | ||
1245 | } | ||
1246 | |||
1247 | if (!_not_derived_from_adverb.empty()) | ||
1248 | { | ||
1249 | std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_id = @NDERADV"); | ||
1250 | std::string cond = "noun_id NOT IN (SELECT noun_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1251 | conditions.push_back(cond); | ||
1252 | } | ||
1253 | |||
1254 | if (!_derived_from_noun.empty()) | ||
1255 | { | ||
1256 | std::list<std::string> clauses(_derived_from_noun.size(), "noun_2_id = @DERN"); | ||
1257 | std::string cond = "noun_id IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1258 | conditions.push_back(cond); | ||
1259 | } | ||
1260 | |||
1261 | if (!_not_derived_from_noun.empty()) | ||
1262 | { | ||
1263 | std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_2_id = @NDERN"); | ||
1264 | std::string cond = "noun_id NOT IN (SELECT noun_1_id FROM noun_noun_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
1265 | conditions.push_back(cond); | ||
1266 | } | ||
1267 | */ | ||
1268 | if (!conditions.empty()) | ||
1269 | { | ||
1270 | construct << " WHERE "; | ||
1271 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
1272 | } | ||
1273 | |||
1274 | if (_random) | ||
1275 | { | ||
1276 | construct << " ORDER BY RANDOM()"; | ||
1277 | } | ||
1278 | |||
1279 | if (_limit != unlimited) | ||
1280 | { | ||
1281 | construct << " LIMIT " << _limit; | ||
1282 | } | ||
1283 | |||
1284 | sqlite3_stmt* ppstmt; | ||
1285 | std::string query = construct.str(); | ||
1286 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
1287 | { | ||
1288 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
1289 | } | ||
1290 | |||
1291 | if (!_rhymes.empty()) | ||
1292 | { | ||
1293 | int i = 0; | ||
1294 | for (auto rhyme : _rhymes) | ||
1295 | { | ||
1296 | std::string rhymer = "%" + rhyme; | ||
1297 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
1298 | |||
1299 | i++; | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | for (auto except : _except) | ||
1304 | { | ||
1305 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
1306 | } | ||
1307 | |||
1308 | for (auto sform : _with_singular_form) | ||
1309 | { | ||
1310 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SFORM"), sform.c_str(), sform.size(), SQLITE_STATIC); | ||
1311 | } | ||
1312 | |||
1313 | for (auto hyponym : _hypernym_of.inorder_flatten()) | ||
1314 | { | ||
1315 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPO"), hyponym._id); | ||
1316 | } | ||
1317 | |||
1318 | for (auto hypernym : _hyponym_of.inorder_flatten()) | ||
1319 | { | ||
1320 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPER"), hypernym._id); | ||
1321 | } | ||
1322 | |||
1323 | for (auto holonym : _part_meronym_of.inorder_flatten()) | ||
1324 | { | ||
1325 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PHOLO"), holonym._id); | ||
1326 | } | ||
1327 | |||
1328 | for (auto meronym : _part_holonym_of.inorder_flatten()) | ||
1329 | { | ||
1330 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PMERO"), meronym._id); | ||
1331 | } | ||
1332 | |||
1333 | for (auto holonym : _substance_meronym_of.inorder_flatten()) | ||
1334 | { | ||
1335 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SHOLO"), holonym._id); | ||
1336 | } | ||
1337 | |||
1338 | for (auto meronym : _substance_holonym_of.inorder_flatten()) | ||
1339 | { | ||
1340 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SMERO"), meronym._id); | ||
1341 | } | ||
1342 | |||
1343 | for (auto holonym : _member_meronym_of.inorder_flatten()) | ||
1344 | { | ||
1345 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MHOLO"), holonym._id); | ||
1346 | } | ||
1347 | |||
1348 | for (auto meronym : _member_holonym_of.inorder_flatten()) | ||
1349 | { | ||
1350 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MMERO"), meronym._id); | ||
1351 | } | ||
1352 | |||
1353 | for (auto cls : _instance_of.inorder_flatten()) | ||
1354 | { | ||
1355 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@CLSID"), cls._id); | ||
1356 | } | ||
1357 | |||
1358 | for (auto inst : _class_of.inorder_flatten()) | ||
1359 | { | ||
1360 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@INSID"), inst._id); | ||
1361 | } | ||
1362 | |||
1363 | for (auto synonym : _synonym_of.inorder_flatten()) | ||
1364 | { | ||
1365 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
1366 | } | ||
1367 | |||
1368 | for (auto antonym : _antonym_of.inorder_flatten()) | ||
1369 | { | ||
1370 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
1371 | } | ||
1372 | |||
1373 | for (auto pertainym : _anti_pertainym_of.inorder_flatten()) | ||
1374 | { | ||
1375 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PERID"), pertainym._id); | ||
1376 | } | ||
1377 | |||
1378 | for (auto value : _attribute_of.inorder_flatten()) | ||
1379 | { | ||
1380 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VALID"), value._id); | ||
1381 | } | ||
1382 | /* | ||
1383 | for (auto adj : _derived_from_adjective) | ||
1384 | { | ||
1385 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id); | ||
1386 | } | ||
1387 | |||
1388 | for (auto adj : _not_derived_from_adjective) | ||
1389 | { | ||
1390 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id); | ||
1391 | } | ||
1392 | |||
1393 | for (auto adv : _derived_from_adverb) | ||
1394 | { | ||
1395 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id); | ||
1396 | } | ||
1397 | |||
1398 | for (auto adv : _not_derived_from_adverb) | ||
1399 | { | ||
1400 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id); | ||
1401 | } | ||
1402 | |||
1403 | for (auto n : _derived_from_noun) | ||
1404 | { | ||
1405 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id); | ||
1406 | } | ||
1407 | |||
1408 | for (auto n : _not_derived_from_noun) | ||
1409 | { | ||
1410 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id); | ||
1411 | } | ||
1412 | */ | ||
1413 | std::list<noun> output; | ||
1414 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
1415 | { | ||
1416 | noun tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
1417 | tnc._singular = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
1418 | |||
1419 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
1420 | { | ||
1421 | tnc._plural = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
1422 | } | ||
1423 | |||
1424 | output.push_back(tnc); | ||
1425 | } | ||
1426 | |||
1427 | sqlite3_finalize(ppstmt); | ||
1428 | |||
1429 | for (auto& noun : output) | ||
1430 | { | ||
1431 | query = "SELECT pronunciation FROM noun_pronunciations WHERE noun_id = ?"; | ||
1432 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
1433 | { | ||
1434 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
1435 | } | ||
1436 | |||
1437 | sqlite3_bind_int(ppstmt, 1, noun._id); | ||
1438 | |||
1439 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
1440 | { | ||
1441 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
1442 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
1443 | |||
1444 | noun.pronunciations.push_back(phonemes); | ||
1445 | } | ||
1446 | |||
1447 | sqlite3_finalize(ppstmt); | ||
1448 | } | ||
1449 | |||
1450 | return output; | ||
1451 | } | ||
1452 | |||
1453 | }; | ||
diff --git a/lib/noun_query.h b/lib/noun_query.h new file mode 100644 index 0000000..0c41a68 --- /dev/null +++ b/lib/noun_query.h | |||
@@ -0,0 +1,139 @@ | |||
1 | #ifndef NOUN_QUERY_H_5DE51DD7 | ||
2 | #define NOUN_QUERY_H_5DE51DD7 | ||
3 | |||
4 | namespace verbly { | ||
5 | |||
6 | class noun_query { | ||
7 | public: | ||
8 | noun_query(const data& _data); | ||
9 | |||
10 | noun_query& limit(int _limit); | ||
11 | noun_query& random(); | ||
12 | noun_query& except(const noun& _word); | ||
13 | noun_query& rhymes_with(const word& _word); | ||
14 | noun_query& has_pronunciation(); | ||
15 | |||
16 | noun_query& with_singular_form(std::string _arg); | ||
17 | |||
18 | noun_query& is_hypernym(); | ||
19 | noun_query& hypernym_of(filter<noun> _f); | ||
20 | noun_query& full_hypernym_of(filter<noun> _f); | ||
21 | |||
22 | noun_query& is_hyponym(); | ||
23 | noun_query& hyponym_of(filter<noun> _f); | ||
24 | noun_query& full_hyponym_of(filter<noun> _f); | ||
25 | |||
26 | noun_query& is_part_meronym(); | ||
27 | noun_query& part_meronym_of(filter<noun> _f); | ||
28 | |||
29 | noun_query& is_part_holonym(); | ||
30 | noun_query& part_holonym_of(filter<noun> _f); | ||
31 | |||
32 | noun_query& is_substance_meronym(); | ||
33 | noun_query& substance_meronym_of(filter<noun> _f); | ||
34 | |||
35 | noun_query& is_substance_holonym(); | ||
36 | noun_query& substance_holonym_of(filter<noun> _f); | ||
37 | |||
38 | noun_query& is_member_meronym(); | ||
39 | noun_query& member_meronym_of(filter<noun> _f); | ||
40 | |||
41 | noun_query& is_member_holonym(); | ||
42 | noun_query& member_holonym_of(filter<noun> _f); | ||
43 | |||
44 | noun_query& is_proper(); | ||
45 | noun_query& is_not_proper(); | ||
46 | |||
47 | noun_query& is_instance(); | ||
48 | noun_query& instance_of(filter<noun> _f); | ||
49 | |||
50 | noun_query& is_class(); | ||
51 | noun_query& class_of(filter<noun> _f); | ||
52 | |||
53 | noun_query& has_synonyms(); | ||
54 | noun_query& synonym_of(filter<noun> _f); | ||
55 | |||
56 | noun_query& has_antonyms(); | ||
57 | noun_query& antonym_of(filter<noun> _f); | ||
58 | |||
59 | noun_query& has_pertainym(); | ||
60 | noun_query& anti_pertainym_of(filter<adjective> _f); | ||
61 | |||
62 | noun_query& is_attribute(); | ||
63 | noun_query& attribute_of(filter<adjective> _f); | ||
64 | |||
65 | /* noun_query& derived_from(const word& _w); | ||
66 | noun_query& not_derived_from(const word& _w);*/ | ||
67 | |||
68 | std::list<noun> run() const; | ||
69 | |||
70 | const static int unlimited = -1; | ||
71 | |||
72 | private: | ||
73 | const data& _data; | ||
74 | int _limit = unlimited; | ||
75 | bool _random = false; | ||
76 | std::list<std::string> _rhymes; | ||
77 | std::list<noun> _except; | ||
78 | bool _has_prn = false; | ||
79 | |||
80 | std::list<std::string> _with_singular_form; | ||
81 | |||
82 | bool _is_hypernym = false; | ||
83 | filter<noun> _hypernym_of; | ||
84 | filter<noun> _full_hypernym_of; | ||
85 | |||
86 | bool _is_hyponym = false; | ||
87 | filter<noun> _hyponym_of; | ||
88 | filter<noun> _full_hyponym_of; | ||
89 | |||
90 | bool _is_part_meronym = false; | ||
91 | filter<noun> _part_meronym_of; | ||
92 | |||
93 | bool _is_substance_meronym = false; | ||
94 | filter<noun> _substance_meronym_of; | ||
95 | |||
96 | bool _is_member_meronym = false; | ||
97 | filter<noun> _member_meronym_of; | ||
98 | |||
99 | bool _is_part_holonym = false; | ||
100 | filter<noun> _part_holonym_of; | ||
101 | |||
102 | bool _is_substance_holonym = false; | ||
103 | filter<noun> _substance_holonym_of; | ||
104 | |||
105 | bool _is_member_holonym = false; | ||
106 | filter<noun> _member_holonym_of; | ||
107 | |||
108 | bool _is_proper = false; | ||
109 | bool _is_not_proper = false; | ||
110 | |||
111 | bool _is_instance = false; | ||
112 | filter<noun> _instance_of; | ||
113 | |||
114 | bool _is_class = false; | ||
115 | filter<noun> _class_of; | ||
116 | |||
117 | bool _has_synonyms = false; | ||
118 | filter<noun> _synonym_of; | ||
119 | |||
120 | bool _has_antonyms = false; | ||
121 | filter<noun> _antonym_of; | ||
122 | |||
123 | bool _has_pertainym = false; | ||
124 | filter<adjective> _anti_pertainym_of; | ||
125 | |||
126 | bool _is_attribute = false; | ||
127 | filter<adjective> _attribute_of; | ||
128 | |||
129 | /* std::list<adjective> _derived_from_adjective; | ||
130 | std::list<adjective> _not_derived_from_adjective; | ||
131 | std::list<adverb> _derived_from_adverb; | ||
132 | std::list<adverb> _not_derived_from_adverb; | ||
133 | std::list<noun> _derived_from_noun; | ||
134 | std::list<noun> _not_derived_from_noun;*/ | ||
135 | }; | ||
136 | |||
137 | }; | ||
138 | |||
139 | #endif /* end of include guard: NOUN_QUERY_H_5DE51DD7 */ | ||
diff --git a/lib/preposition.cpp b/lib/preposition.cpp new file mode 100644 index 0000000..c619bbf --- /dev/null +++ b/lib/preposition.cpp | |||
@@ -0,0 +1,83 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | std::string preposition::get_form() const | ||
6 | { | ||
7 | return form; | ||
8 | } | ||
9 | |||
10 | preposition_query::preposition_query(const data& _data) : _data(_data) | ||
11 | { | ||
12 | |||
13 | } | ||
14 | |||
15 | preposition_query& preposition_query::limit(int _limit) | ||
16 | { | ||
17 | this->_limit = _limit; | ||
18 | |||
19 | return *this; | ||
20 | } | ||
21 | |||
22 | preposition_query& preposition_query::random() | ||
23 | { | ||
24 | _random = true; | ||
25 | |||
26 | return *this; | ||
27 | } | ||
28 | |||
29 | preposition_query& preposition_query::in_group(std::string _arg) | ||
30 | { | ||
31 | _in_group.push_back(_arg); | ||
32 | |||
33 | return *this; | ||
34 | } | ||
35 | |||
36 | std::list<preposition> preposition_query::run() const | ||
37 | { | ||
38 | std::stringstream construct; | ||
39 | construct << "SELECT form FROM prepositions"; | ||
40 | |||
41 | if (!_in_group.empty()) | ||
42 | { | ||
43 | std::list<std::string> clauses(_in_group.size(), "groupname = @GNAME"); | ||
44 | construct << " WHERE preposition_id IN (SELECT preposition_id FROM preposition_groups WHERE "; | ||
45 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); | ||
46 | construct << ")"; | ||
47 | } | ||
48 | |||
49 | if (_random) | ||
50 | { | ||
51 | construct << " ORDER BY RANDOM()"; | ||
52 | } | ||
53 | |||
54 | if (_limit != unlimited) | ||
55 | { | ||
56 | construct << " LIMIT " << _limit; | ||
57 | } | ||
58 | |||
59 | sqlite3_stmt* ppstmt; | ||
60 | std::string query = construct.str(); | ||
61 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
62 | { | ||
63 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
64 | } | ||
65 | |||
66 | for (auto& group : _in_group) | ||
67 | { | ||
68 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GNAME"), group.c_str(), group.length(), SQLITE_STATIC); | ||
69 | } | ||
70 | |||
71 | std::list<preposition> output; | ||
72 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
73 | { | ||
74 | preposition pp; | ||
75 | pp.form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
76 | |||
77 | output.push_back(pp); | ||
78 | } | ||
79 | |||
80 | return output; | ||
81 | } | ||
82 | |||
83 | }; | ||
diff --git a/lib/preposition.h b/lib/preposition.h new file mode 100644 index 0000000..89f24fa --- /dev/null +++ b/lib/preposition.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef PREPOSITION_H_FF908021 | ||
2 | #define PREPOSITION_H_FF908021 | ||
3 | |||
4 | namespace verbly { | ||
5 | |||
6 | class preposition_query; | ||
7 | |||
8 | class preposition { | ||
9 | public: | ||
10 | std::string get_form() const; | ||
11 | |||
12 | private: | ||
13 | friend class preposition_query; | ||
14 | |||
15 | std::string form; | ||
16 | }; | ||
17 | |||
18 | class preposition_query { | ||
19 | public: | ||
20 | preposition_query(const data& _data); | ||
21 | |||
22 | preposition_query& limit(int _limit); | ||
23 | preposition_query& random(); | ||
24 | preposition_query& in_group(std::string _arg); | ||
25 | |||
26 | std::list<preposition> run() const; | ||
27 | |||
28 | const static int unlimited = -1; | ||
29 | private: | ||
30 | const data& _data; | ||
31 | int _limit = unlimited; | ||
32 | bool _random = false; | ||
33 | std::list<std::string> _in_group; | ||
34 | }; | ||
35 | |||
36 | }; | ||
37 | |||
38 | #endif /* end of include guard: PREPOSITION_H_FF908021 */ | ||
diff --git a/lib/token.cpp b/lib/token.cpp index facab8a..1e25acb 100644 --- a/lib/token.cpp +++ b/lib/token.cpp | |||
@@ -2,52 +2,627 @@ | |||
2 | 2 | ||
3 | namespace verbly { | 3 | namespace verbly { |
4 | 4 | ||
5 | token::token(token::type _type) : _type(_type) | 5 | token::type token::get_type() const |
6 | { | 6 | { |
7 | 7 | return _type; | |
8 | } | 8 | } |
9 | 9 | ||
10 | token::type token::token_type() const | 10 | int token::get_extra() const |
11 | { | 11 | { |
12 | return _type; | 12 | return _extra; |
13 | } | 13 | } |
14 | 14 | ||
15 | verb_token::verb_token(const verb& _verb) : token(token::type::verb), _verb(&_verb) | 15 | void token::set_extra(int _arg) |
16 | { | 16 | { |
17 | 17 | _extra = _arg; | |
18 | } | 18 | } |
19 | 19 | ||
20 | const verb& verb_token::get_verb() const | 20 | token::token(const token& other) |
21 | { | 21 | { |
22 | return *_verb; | 22 | _type = other._type; |
23 | |||
24 | switch (_type) | ||
25 | { | ||
26 | case token::type::verb: | ||
27 | { | ||
28 | new(&_verb._verb) verb(other._verb._verb); | ||
29 | _verb._infl = other._verb._infl; | ||
30 | |||
31 | break; | ||
32 | } | ||
33 | |||
34 | case token::type::noun: | ||
35 | { | ||
36 | new(&_noun._noun) noun(other._noun._noun); | ||
37 | _noun._infl = other._noun._infl; | ||
38 | |||
39 | break; | ||
40 | } | ||
41 | |||
42 | case token::type::adjective: | ||
43 | { | ||
44 | new(&_adjective._adjective) adjective(other._adjective._adjective); | ||
45 | _adjective._infl = other._adjective._infl; | ||
46 | |||
47 | break; | ||
48 | } | ||
49 | |||
50 | case token::type::adverb: | ||
51 | { | ||
52 | new(&_adverb._adverb) adverb(other._adverb._adverb); | ||
53 | _adverb._infl = other._adverb._infl; | ||
54 | |||
55 | break; | ||
56 | } | ||
57 | |||
58 | case token::type::preposition: | ||
59 | { | ||
60 | new(&_preposition._preposition) preposition(other._preposition._preposition); | ||
61 | |||
62 | break; | ||
63 | } | ||
64 | |||
65 | case token::type::fillin: | ||
66 | { | ||
67 | _fillin._type = other._fillin._type; | ||
68 | |||
69 | break; | ||
70 | } | ||
71 | |||
72 | case token::type::string: | ||
73 | { | ||
74 | new(&_string._str) std::string(other._string._str); | ||
75 | |||
76 | break; | ||
77 | } | ||
78 | |||
79 | case token::type::utterance: | ||
80 | { | ||
81 | new(&_utterance._utterance) std::list<token>(other._utterance._utterance); | ||
82 | |||
83 | break; | ||
84 | } | ||
85 | } | ||
23 | } | 86 | } |
24 | 87 | ||
25 | verb_token& verb_token::inflect(verb_token::inflection infl) | 88 | token& token::operator=(const token& other) |
26 | { | 89 | { |
27 | _inflection = infl; | 90 | this->~token(); |
91 | |||
92 | _type = other._type; | ||
93 | |||
94 | switch (_type) | ||
95 | { | ||
96 | case token::type::verb: | ||
97 | { | ||
98 | new(&_verb._verb) verb(other._verb._verb); | ||
99 | _verb._infl = other._verb._infl; | ||
100 | |||
101 | break; | ||
102 | } | ||
103 | |||
104 | case token::type::noun: | ||
105 | { | ||
106 | new(&_noun._noun) noun(other._noun._noun); | ||
107 | _noun._infl = other._noun._infl; | ||
108 | |||
109 | break; | ||
110 | } | ||
111 | |||
112 | case token::type::adjective: | ||
113 | { | ||
114 | new(&_adjective._adjective) adjective(other._adjective._adjective); | ||
115 | _adjective._infl = other._adjective._infl; | ||
116 | |||
117 | break; | ||
118 | } | ||
119 | |||
120 | case token::type::adverb: | ||
121 | { | ||
122 | new(&_adverb._adverb) adverb(other._adverb._adverb); | ||
123 | _adverb._infl = other._adverb._infl; | ||
124 | |||
125 | break; | ||
126 | } | ||
127 | |||
128 | case token::type::preposition: | ||
129 | { | ||
130 | new(&_preposition._preposition) preposition(other._preposition._preposition); | ||
131 | |||
132 | break; | ||
133 | } | ||
134 | |||
135 | case token::type::fillin: | ||
136 | { | ||
137 | _fillin._type = other._fillin._type; | ||
138 | |||
139 | break; | ||
140 | } | ||
141 | |||
142 | case token::type::string: | ||
143 | { | ||
144 | new(&_string._str) std::string(other._string._str); | ||
145 | |||
146 | break; | ||
147 | } | ||
148 | |||
149 | case token::type::utterance: | ||
150 | { | ||
151 | new(&_utterance._utterance) std::list<token>(other._utterance._utterance); | ||
152 | |||
153 | break; | ||
154 | } | ||
155 | } | ||
156 | |||
28 | return *this; | 157 | return *this; |
29 | } | 158 | } |
30 | 159 | ||
31 | bool verb_token::complete() const | 160 | token::~token() |
32 | { | 161 | { |
33 | return true; | 162 | switch (_type) |
163 | { | ||
164 | case token::type::verb: | ||
165 | { | ||
166 | _verb._verb.~verb(); | ||
167 | |||
168 | break; | ||
169 | } | ||
170 | |||
171 | case token::type::noun: | ||
172 | { | ||
173 | _noun._noun.~noun(); | ||
174 | |||
175 | break; | ||
176 | } | ||
177 | |||
178 | case token::type::adjective: | ||
179 | { | ||
180 | _adjective._adjective.~adjective(); | ||
181 | |||
182 | break; | ||
183 | } | ||
184 | |||
185 | case token::type::adverb: | ||
186 | { | ||
187 | _adverb._adverb.~adverb(); | ||
188 | |||
189 | break; | ||
190 | } | ||
191 | |||
192 | case token::type::preposition: | ||
193 | { | ||
194 | _preposition._preposition.~preposition(); | ||
195 | |||
196 | break; | ||
197 | } | ||
198 | |||
199 | case token::type::fillin: | ||
200 | { | ||
201 | // Nothing! | ||
202 | |||
203 | break; | ||
204 | } | ||
205 | |||
206 | case token::type::string: | ||
207 | { | ||
208 | using string_type = std::string; | ||
209 | _string._str.~string_type(); | ||
210 | |||
211 | break; | ||
212 | } | ||
213 | |||
214 | case token::type::utterance: | ||
215 | { | ||
216 | using list_type = std::list<token>; | ||
217 | _utterance._utterance.~list_type(); | ||
218 | |||
219 | break; | ||
220 | } | ||
221 | } | ||
34 | } | 222 | } |
35 | 223 | ||
36 | std::string verb_token::compile() const | 224 | bool token::is_complete() const |
37 | { | 225 | { |
38 | switch (_inflection) | 226 | if (_type == token::type::utterance) |
39 | { | 227 | { |
40 | case inflection::infinitive: return _verb->infinitive_form(); | 228 | return std::all_of(std::begin(_utterance._utterance), std::end(_utterance._utterance), [] (const token& tkn) { |
41 | case inflection::past_tense: return _verb->past_tense_form(); | 229 | return tkn.is_complete(); |
42 | case inflection::past_participle: return _verb->past_participle_form(); | 230 | }); |
43 | case inflection::ing_form: return _verb->ing_form(); | 231 | } else if (_type == token::type::fillin) |
44 | case inflection::s_form: return _verb->s_form(); | 232 | { |
233 | return false; | ||
234 | } else { | ||
235 | return true; | ||
45 | } | 236 | } |
46 | } | 237 | } |
47 | 238 | ||
48 | token* verb_token::copy() const | 239 | std::string token::compile() const |
240 | { | ||
241 | switch (_type) | ||
242 | { | ||
243 | case token::type::verb: | ||
244 | { | ||
245 | switch (_verb._infl) | ||
246 | { | ||
247 | case token::verb_inflection::infinitive: return _verb._verb.infinitive_form(); | ||
248 | case token::verb_inflection::past_tense: return _verb._verb.past_tense_form(); | ||
249 | case token::verb_inflection::past_participle: return _verb._verb.past_participle_form(); | ||
250 | case token::verb_inflection::ing_form: return _verb._verb.ing_form(); | ||
251 | case token::verb_inflection::s_form: return _verb._verb.s_form(); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | case token::type::noun: | ||
256 | { | ||
257 | switch (_noun._infl) | ||
258 | { | ||
259 | case token::noun_inflection::singular: return _noun._noun.singular_form(); | ||
260 | case token::noun_inflection::plural: return _noun._noun.plural_form(); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | case token::type::adjective: | ||
265 | { | ||
266 | switch (_adjective._infl) | ||
267 | { | ||
268 | case token::adjective_inflection::base: return _adjective._adjective.base_form(); | ||
269 | case token::adjective_inflection::comparative: return _adjective._adjective.comparative_form(); | ||
270 | case token::adjective_inflection::superlative: return _adjective._adjective.superlative_form(); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | case token::type::adverb: | ||
275 | { | ||
276 | switch (_adverb._infl) | ||
277 | { | ||
278 | case token::adverb_inflection::base: return _adverb._adverb.base_form(); | ||
279 | case token::adverb_inflection::comparative: return _adverb._adverb.comparative_form(); | ||
280 | case token::adverb_inflection::superlative: return _adverb._adverb.superlative_form(); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | case token::type::preposition: return _preposition._preposition.get_form(); | ||
285 | case token::type::string: return _string._str; | ||
286 | |||
287 | case token::type::fillin: | ||
288 | { | ||
289 | throw std::runtime_error("Cannot compile a fillin token."); | ||
290 | } | ||
291 | |||
292 | case token::type::utterance: | ||
293 | { | ||
294 | std::list<std::string> compiled; | ||
295 | std::transform(std::begin(_utterance._utterance), std::end(_utterance._utterance), std::back_inserter(compiled), [] (token tkn) { | ||
296 | return tkn.compile(); | ||
297 | }); | ||
298 | |||
299 | return verbly::implode(std::begin(compiled), std::end(compiled), " "); | ||
300 | } | ||
301 | } | ||
302 | } | ||
303 | |||
304 | token::token(verb _verb) : _type(type::verb) | ||
305 | { | ||
306 | new(&this->_verb._verb) verb(_verb); | ||
307 | this->_verb._infl = verb_inflection::infinitive; | ||
308 | } | ||
309 | |||
310 | token::token(verb _verb, verb_inflection _infl) : token(_verb) | ||
311 | { | ||
312 | this->_verb._infl = _infl; | ||
313 | } | ||
314 | |||
315 | token& token::operator=(verb _verb) | ||
316 | { | ||
317 | *this = token{_verb}; | ||
318 | |||
319 | return *this; | ||
320 | } | ||
321 | |||
322 | verb token::get_verb() const | ||
323 | { | ||
324 | assert(_type == type::verb); | ||
325 | |||
326 | return _verb._verb; | ||
327 | } | ||
328 | |||
329 | void token::set_verb(verb _verb) | ||
330 | { | ||
331 | assert(_type == type::verb); | ||
332 | |||
333 | this->_verb._verb = _verb; | ||
334 | } | ||
335 | |||
336 | token::verb_inflection token::get_verb_inflection() const | ||
337 | { | ||
338 | assert(_type == type::verb); | ||
339 | |||
340 | return _verb._infl; | ||
341 | } | ||
342 | |||
343 | void token::set_verb_inflection(verb_inflection _infl) | ||
344 | { | ||
345 | assert(_type == type::verb); | ||
346 | |||
347 | _verb._infl = _infl; | ||
348 | } | ||
349 | |||
350 | token::token(noun _noun) : _type(type::noun) | ||
351 | { | ||
352 | new(&this->_noun._noun) noun(_noun); | ||
353 | this->_noun._infl = noun_inflection::singular; | ||
354 | } | ||
355 | |||
356 | token::token(noun _noun, noun_inflection _infl) : token(_noun) | ||
357 | { | ||
358 | this->_noun._infl = _infl; | ||
359 | } | ||
360 | |||
361 | token& token::operator=(noun _noun) | ||
49 | { | 362 | { |
50 | return new verb_token(*this); | 363 | *this = token{_noun}; |
364 | |||
365 | return *this; | ||
366 | } | ||
367 | |||
368 | noun token::get_noun() const | ||
369 | { | ||
370 | assert(_type == type::noun); | ||
371 | |||
372 | return _noun._noun; | ||
373 | } | ||
374 | |||
375 | void token::set_noun(noun _noun) | ||
376 | { | ||
377 | assert(_type == type::noun); | ||
378 | |||
379 | this->_noun._noun = _noun; | ||
380 | } | ||
381 | |||
382 | token::noun_inflection token::get_noun_inflection() const | ||
383 | { | ||
384 | assert(_type == type::noun); | ||
385 | |||
386 | return _noun._infl; | ||
387 | } | ||
388 | |||
389 | void token::set_noun_inflection(noun_inflection _infl) | ||
390 | { | ||
391 | assert(_type == type::noun); | ||
392 | |||
393 | _noun._infl = _infl; | ||
394 | } | ||
395 | |||
396 | token::token(adjective _adjective) : _type(type::adjective) | ||
397 | { | ||
398 | new(&this->_adjective._adjective) adjective(_adjective); | ||
399 | this->_adjective._infl = adjective_inflection::base; | ||
400 | } | ||
401 | |||
402 | token::token(adjective _adjective, adjective_inflection _infl) : token(_adjective) | ||
403 | { | ||
404 | this->_adjective._infl = _infl; | ||
405 | } | ||
406 | |||
407 | token& token::operator=(adjective _adjective) | ||
408 | { | ||
409 | *this = token{_adjective}; | ||
410 | |||
411 | return *this; | ||
412 | } | ||
413 | |||
414 | adjective token::get_adjective() const | ||
415 | { | ||
416 | assert(_type == type::adjective); | ||
417 | |||
418 | return _adjective._adjective; | ||
419 | } | ||
420 | |||
421 | void token::set_adjective(adjective _adjective) | ||
422 | { | ||
423 | assert(_type == type::adjective); | ||
424 | |||
425 | this->_adjective._adjective = _adjective; | ||
426 | } | ||
427 | |||
428 | token::adjective_inflection token::get_adjective_inflection() const | ||
429 | { | ||
430 | assert(_type == type::adjective); | ||
431 | |||
432 | return _adjective._infl; | ||
433 | } | ||
434 | |||
435 | void token::set_adjective_inflection(adjective_inflection _infl) | ||
436 | { | ||
437 | assert(_type == type::adjective); | ||
438 | |||
439 | _adjective._infl = _infl; | ||
440 | } | ||
441 | |||
442 | token::token(adverb _adverb) : _type(type::adverb) | ||
443 | { | ||
444 | new(&this->_adverb._adverb) adverb(_adverb); | ||
445 | this->_adverb._infl = adverb_inflection::base; | ||
446 | } | ||
447 | |||
448 | token::token(adverb _adverb, adverb_inflection _infl) : token(_adverb) | ||
449 | { | ||
450 | this->_adverb._infl = _infl; | ||
451 | } | ||
452 | |||
453 | token& token::operator=(adverb _adverb) | ||
454 | { | ||
455 | *this = token{_adverb}; | ||
456 | |||
457 | return *this; | ||
458 | } | ||
459 | |||
460 | adverb token::get_adverb() const | ||
461 | { | ||
462 | assert(_type == type::adverb); | ||
463 | |||
464 | return _adverb._adverb; | ||
465 | } | ||
466 | |||
467 | void token::set_adverb(adverb _adverb) | ||
468 | { | ||
469 | assert(_type == type::adverb); | ||
470 | |||
471 | this->_adverb._adverb = _adverb; | ||
472 | } | ||
473 | |||
474 | token::adverb_inflection token::get_adverb_inflection() const | ||
475 | { | ||
476 | assert(_type == type::adverb); | ||
477 | |||
478 | return _adverb._infl; | ||
479 | } | ||
480 | |||
481 | void token::set_adverb_inflection(adverb_inflection _infl) | ||
482 | { | ||
483 | assert(_type == type::adverb); | ||
484 | |||
485 | _adverb._infl = _infl; | ||
486 | } | ||
487 | |||
488 | token::token(preposition _preposition) : _type(type::preposition) | ||
489 | { | ||
490 | new(&this->_preposition._preposition) preposition(_preposition); | ||
491 | } | ||
492 | |||
493 | token& token::operator=(preposition _preposition) | ||
494 | { | ||
495 | *this = token{_preposition}; | ||
496 | |||
497 | return *this; | ||
498 | } | ||
499 | |||
500 | preposition token::get_preposition() const | ||
501 | { | ||
502 | assert(_type == type::preposition); | ||
503 | |||
504 | return _preposition._preposition; | ||
505 | } | ||
506 | |||
507 | void token::set_preposition(preposition _preposition) | ||
508 | { | ||
509 | assert(_type == type::preposition); | ||
510 | |||
511 | this->_preposition._preposition = _preposition; | ||
512 | } | ||
513 | |||
514 | token::token(fillin_type _ft) : _type(type::fillin) | ||
515 | { | ||
516 | _fillin._type = _ft; | ||
517 | } | ||
518 | |||
519 | token& token::operator=(fillin_type _ft) | ||
520 | { | ||
521 | *this = token{_ft}; | ||
522 | |||
523 | return *this; | ||
524 | } | ||
525 | |||
526 | token::fillin_type token::get_fillin_type() const | ||
527 | { | ||
528 | assert(_type == type::fillin); | ||
529 | |||
530 | return _fillin._type; | ||
531 | } | ||
532 | |||
533 | void token::set_fillin_type(fillin_type _ft) | ||
534 | { | ||
535 | assert(_type == type::fillin); | ||
536 | |||
537 | _fillin._type = _ft; | ||
538 | } | ||
539 | |||
540 | token::token() : _type(type::utterance) | ||
541 | { | ||
542 | new(&_utterance._utterance) std::list<token>(); | ||
543 | } | ||
544 | |||
545 | token::token(std::initializer_list<token> _init) : _type(type::utterance) | ||
546 | { | ||
547 | new(&_utterance._utterance) std::list<token>(_init); | ||
548 | } | ||
549 | |||
550 | token::iterator token::begin() | ||
551 | { | ||
552 | assert(_type == type::utterance); | ||
553 | |||
554 | return _utterance._utterance.begin(); | ||
555 | } | ||
556 | |||
557 | token::iterator token::end() | ||
558 | { | ||
559 | assert(_type == type::utterance); | ||
560 | |||
561 | return _utterance._utterance.end(); | ||
562 | } | ||
563 | |||
564 | token& token::operator<<(token _tkn) | ||
565 | { | ||
566 | assert(_type == type::utterance); | ||
567 | |||
568 | _utterance._utterance.push_back(_tkn); | ||
569 | |||
570 | return *this; | ||
571 | } | ||
572 | |||
573 | void token::push_back(token _tkn) | ||
574 | { | ||
575 | assert(_type == type::utterance); | ||
576 | |||
577 | _utterance._utterance.push_back(_tkn); | ||
578 | } | ||
579 | |||
580 | void token::insert(iterator before, token _tkn) | ||
581 | { | ||
582 | assert(_type == type::utterance); | ||
583 | |||
584 | _utterance._utterance.insert(before, _tkn); | ||
585 | } | ||
586 | |||
587 | void token::replace(iterator torepl, token _tkn) | ||
588 | { | ||
589 | assert(_type == type::utterance); | ||
590 | |||
591 | _utterance._utterance.insert(torepl, _tkn); | ||
592 | _utterance._utterance.erase(torepl); | ||
593 | } | ||
594 | |||
595 | void token::erase(iterator toer) | ||
596 | { | ||
597 | assert(_type == type::utterance); | ||
598 | |||
599 | _utterance._utterance.erase(toer); | ||
600 | } | ||
601 | |||
602 | token::token(std::string _str) : _type(type::string) | ||
603 | { | ||
604 | new(&_string._str) std::string(_str); | ||
605 | } | ||
606 | |||
607 | token& token::operator=(std::string _str) | ||
608 | { | ||
609 | *this = token{_str}; | ||
610 | |||
611 | return *this; | ||
612 | } | ||
613 | |||
614 | std::string token::get_string() const | ||
615 | { | ||
616 | assert(_type == type::string); | ||
617 | |||
618 | return _string._str; | ||
619 | } | ||
620 | |||
621 | void token::set_string(std::string _str) | ||
622 | { | ||
623 | assert(_type == type::string); | ||
624 | |||
625 | _string._str = _str; | ||
51 | } | 626 | } |
52 | 627 | ||
53 | }; | 628 | }; |
diff --git a/lib/token.h b/lib/token.h index b22032b..788a106 100644 --- a/lib/token.h +++ b/lib/token.h | |||
@@ -1,314 +1,169 @@ | |||
1 | #ifndef TOKEN_H_AD62C505 | 1 | #ifndef TOKEN_H_AD62C505 |
2 | #define TOKEN_H_AD62C505 | 2 | #define TOKEN_H_AD62C505 |
3 | 3 | ||
4 | #include <string> | ||
5 | #include <list> | ||
6 | #include <sstream> | ||
7 | #include <algorithm> | ||
8 | |||
9 | namespace verbly { | 4 | namespace verbly { |
10 | 5 | ||
11 | class verb; | ||
12 | |||
13 | class selrestr { | ||
14 | }; | ||
15 | |||
16 | class synrestr { | ||
17 | }; | ||
18 | |||
19 | enum class fillin_type { | ||
20 | noun_phrase, | ||
21 | participle_phrase, | ||
22 | adjective, | ||
23 | adverb | ||
24 | }; | ||
25 | |||
26 | class token { | 6 | class token { |
27 | public: | 7 | public: |
28 | enum class type { | 8 | enum class type { |
29 | verb, | 9 | verb, |
10 | noun, | ||
11 | adjective, | ||
12 | adverb, | ||
13 | preposition, | ||
30 | fillin, | 14 | fillin, |
31 | string, | 15 | utterance, |
32 | utterance | 16 | string |
33 | }; | 17 | }; |
34 | 18 | ||
35 | protected: | 19 | enum class verb_inflection { |
36 | // General | ||
37 | type _type; | ||
38 | |||
39 | token(type _type); | ||
40 | |||
41 | public: | ||
42 | enum type token_type() const; | ||
43 | |||
44 | virtual bool complete() const = 0; | ||
45 | virtual std::string compile() const = 0; | ||
46 | virtual token* copy() const = 0; | ||
47 | }; | ||
48 | |||
49 | class verb_token : public token { | ||
50 | public: | ||
51 | enum class inflection { | ||
52 | infinitive, | 20 | infinitive, |
53 | past_tense, | 21 | past_tense, |
54 | past_participle, | 22 | past_participle, |
55 | ing_form, | 23 | s_form, |
56 | s_form | 24 | ing_form |
57 | }; | 25 | }; |
58 | 26 | ||
59 | private: | 27 | enum class noun_inflection { |
60 | // Verb | 28 | singular, |
61 | const verb* _verb; | 29 | plural |
62 | inflection _inflection = inflection::infinitive; | 30 | }; |
63 | |||
64 | public: | ||
65 | verb_token(const verb& _verb); | ||
66 | |||
67 | const verb& get_verb() const; | ||
68 | |||
69 | verb_token& inflect(inflection infl); | ||
70 | |||
71 | bool complete() const; | ||
72 | |||
73 | std::string compile() const; | ||
74 | |||
75 | token* copy() const; | ||
76 | }; | ||
77 | |||
78 | class utterance_token : public token { | ||
79 | private: | ||
80 | // Utterance | ||
81 | std::list<std::unique_ptr<token>> utterance; | ||
82 | |||
83 | public: | ||
84 | typedef std::list<std::unique_ptr<token>>::iterator iterator; | ||
85 | /*class iterator { | ||
86 | private: | ||
87 | friend class utterance_token; | ||
88 | |||
89 | std::list<std::unique_ptr<token>>::iterator it; | ||
90 | |||
91 | public: | ||
92 | iterator(std::list<std::unique_ptr<token>>::iterator it) : it(it) | ||
93 | { | ||
94 | |||
95 | } | ||
96 | |||
97 | iterator& operator++() | ||
98 | { | ||
99 | ++it; | ||
100 | return *this; | ||
101 | } | ||
102 | |||
103 | iterator& operator--() | ||
104 | { | ||
105 | --it; | ||
106 | return *this; | ||
107 | } | ||
108 | |||
109 | bool operator==(const iterator& other) const | ||
110 | { | ||
111 | return it == other.it; | ||
112 | } | ||
113 | |||
114 | bool operator!=(const iterator& other) const | ||
115 | { | ||
116 | return it != other.it; | ||
117 | } | ||
118 | |||
119 | token& operator*() | ||
120 | { | ||
121 | return **it; | ||
122 | } | ||
123 | |||
124 | token& operator->() | ||
125 | { | ||
126 | return **it; | ||
127 | } | ||
128 | };*/ | ||
129 | |||
130 | utterance_token(std::initializer_list<token*> tkns) : token(token::type::utterance) | ||
131 | { | ||
132 | for (auto tkn : tkns) | ||
133 | { | ||
134 | utterance.push_back(std::unique_ptr<token>(tkn)); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | utterance_token(const utterance_token& other) : token(token::type::utterance) | ||
139 | { | ||
140 | for (auto& tkn : other.utterance) | ||
141 | { | ||
142 | utterance.push_back(std::unique_ptr<token>(tkn->copy())); | ||
143 | } | ||
144 | } | ||
145 | 31 | ||
146 | utterance_token(utterance_token&& other) : token(token::type::utterance), utterance(std::move(other.utterance)) | 32 | enum class adjective_inflection { |
147 | { | 33 | base, |
148 | 34 | comparative, | |
149 | } | 35 | superlative |
36 | }; | ||
150 | 37 | ||
151 | utterance_token& operator=(const utterance_token& other) | 38 | enum class adverb_inflection { |
152 | { | 39 | base, |
153 | utterance.clear(); | 40 | comparative, |
154 | 41 | superlative | |
155 | for (auto& tkn : other.utterance) | 42 | }; |
156 | { | ||
157 | utterance.push_back(std::unique_ptr<token>(tkn->copy())); | ||
158 | } | ||
159 | |||
160 | return *this; | ||
161 | } | ||
162 | 43 | ||
163 | utterance_token& operator=(utterance_token&& other) | 44 | enum class fillin_type { |
164 | { | 45 | generic, |
165 | utterance = std::move(other.utterance); | 46 | noun_phrase, |
166 | 47 | adjective_phrase, | |
167 | return *this; | 48 | adverb_phrase, |
168 | } | 49 | participle_phrase, |
50 | infinitive_phrase | ||
51 | }; | ||
169 | 52 | ||
170 | iterator begin() | 53 | type get_type() const; |
171 | { | ||
172 | return std::begin(utterance); | ||
173 | } | ||
174 | 54 | ||
175 | iterator end() | 55 | int get_extra() const; |
176 | { | 56 | void set_extra(int _arg); |
177 | return std::end(utterance); | ||
178 | } | ||
179 | 57 | ||
180 | void erase(iterator it) | 58 | token(const token& other); |
181 | { | 59 | token& operator=(const token& other); |
182 | utterance.erase(it); | 60 | ~token(); |
183 | } | ||
184 | 61 | ||
185 | bool complete() const | 62 | bool is_complete() const; |
186 | { | 63 | std::string compile() const; |
187 | return std::all_of(std::begin(utterance), std::end(utterance), [] (const std::unique_ptr<token>& tkn) { | ||
188 | return tkn->complete(); | ||
189 | }); | ||
190 | } | ||
191 | 64 | ||
192 | std::string compile() const | 65 | // Verb |
193 | { | 66 | token(verb _verb); |
194 | std::stringstream result; | 67 | token(verb _verb, verb_inflection _infl); |
195 | for (auto& t : utterance) | 68 | token& operator=(verb _verb); |
196 | { | 69 | verb get_verb() const; |
197 | if (t->complete()) | 70 | void set_verb(verb _verb); |
198 | { | 71 | verb_inflection get_verb_inflection() const; |
199 | result << t->compile() << " "; | 72 | void set_verb_inflection(verb_inflection _infl); |
200 | } else { | 73 | |
201 | return "Could not compile!"; | 74 | // Noun |
202 | } | 75 | token(noun _noun); |
203 | } | 76 | token(noun _noun, noun_inflection _infl); |
204 | 77 | token& operator=(noun _noun); | |
205 | std::string output = result.str(); | 78 | noun get_noun() const; |
206 | if (output != "") | 79 | void set_noun(noun _noun); |
207 | { | 80 | noun_inflection get_noun_inflection() const; |
208 | output.pop_back(); | 81 | void set_noun_inflection(noun_inflection _infl); |
209 | } | 82 | |
210 | 83 | // Adjective | |
211 | return output; | 84 | token(adjective _adjective); |
212 | } | 85 | token(adjective _adjective, adjective_inflection _infl); |
86 | token& operator=(adjective _adjective); | ||
87 | adjective get_adjective() const; | ||
88 | void set_adjective(adjective _adjective); | ||
89 | adjective_inflection get_adjective_inflection() const; | ||
90 | void set_adjective_inflection(adjective_inflection _infl); | ||
91 | |||
92 | // Adverb | ||
93 | token(adverb _adverb); | ||
94 | token(adverb _adverb, adverb_inflection _infl); | ||
95 | token& operator=(adverb _adverb); | ||
96 | adverb get_adverb() const; | ||
97 | void set_adverb(adverb _adverb); | ||
98 | adverb_inflection get_adverb_inflection() const; | ||
99 | void set_adverb_inflection(adverb_inflection _infl); | ||
100 | |||
101 | // Preposition | ||
102 | token(preposition _preposition); | ||
103 | token& operator=(preposition _preposition); | ||
104 | preposition get_preposition() const; | ||
105 | void set_preposition(preposition _preposition); | ||
213 | 106 | ||
214 | token* copy() const | ||
215 | { | ||
216 | return new utterance_token(*this); | ||
217 | } | ||
218 | }; | ||
219 | |||
220 | class fillin_token : public token { | ||
221 | private: | ||
222 | // Fillin | 107 | // Fillin |
223 | std::string m_theme; | 108 | token(fillin_type _ft); |
224 | fillin_type m_fillin_type; | 109 | token& operator=(fillin_type _ft); |
225 | 110 | fillin_type get_fillin_type() const; | |
226 | public: | 111 | void set_fillin_type(fillin_type _ft); |
227 | fillin_token(fillin_type ft) : token(token::type::fillin), m_fillin_type(ft) | ||
228 | { | ||
229 | |||
230 | } | ||
231 | |||
232 | /* void synrestrs(std::initializer_list<synrestr> ins) | ||
233 | { | ||
234 | m_synrestrs = std::set<synrestr>(ins); | ||
235 | } | ||
236 | |||
237 | std::set<synrestr>& synrestrs() | ||
238 | { | ||
239 | return m_synrestrs; | ||
240 | } | ||
241 | |||
242 | void selrestrs(std::initializer_list<selrestr> ins) | ||
243 | { | ||
244 | m_selrestrs = std::set<selrestr>(ins); | ||
245 | } | ||
246 | |||
247 | std::set<selrestr>& selrestrs() | ||
248 | { | ||
249 | return m_selrestrs; | ||
250 | }*/ | ||
251 | |||
252 | fillin_token theme(std::string theme) | ||
253 | { | ||
254 | m_theme = theme; | ||
255 | |||
256 | return *this; | ||
257 | } | ||
258 | 112 | ||
259 | std::string& theme() | 113 | // Utterance |
260 | { | 114 | typedef std::list<token>::iterator iterator; |
261 | return m_theme; | 115 | |
262 | } | 116 | token(); |
263 | 117 | token(std::initializer_list<token> _init); | |
264 | fillin_type get_fillin_type() const | 118 | iterator begin(); |
265 | { | 119 | iterator end(); |
266 | return m_fillin_type; | 120 | token& operator<<(token _tkn); |
267 | } | 121 | void push_back(token _tkn); |
268 | 122 | void insert(iterator before, token _tkn); | |
269 | bool complete() const | 123 | void replace(iterator torepl, token _tkn); |
270 | { | 124 | void erase(iterator toer); |
271 | return false; | ||
272 | } | ||
273 | |||
274 | std::string compile() const | ||
275 | { | ||
276 | return ""; | ||
277 | } | ||
278 | 125 | ||
279 | token* copy() const | ||
280 | { | ||
281 | return new fillin_token(*this); | ||
282 | } | ||
283 | }; | ||
284 | |||
285 | class string_token : public token { | ||
286 | private: | ||
287 | // String | 126 | // String |
288 | std::string str; | 127 | token(std::string _str); |
289 | 128 | token& operator=(std::string _str); | |
290 | public: | 129 | std::string get_string() const; |
291 | string_token(std::string str) : token(token::type::string), str(str) | 130 | void set_string(std::string _str); |
292 | { | ||
293 | |||
294 | } | ||
295 | |||
296 | bool complete() const | ||
297 | { | ||
298 | return true; | ||
299 | } | ||
300 | 131 | ||
301 | std::string compile() const | 132 | private: |
302 | { | 133 | type _type; |
303 | return str; | 134 | int _extra = 0; |
304 | } | 135 | union { |
305 | 136 | struct { | |
306 | token* copy() const | 137 | verb _verb; |
307 | { | 138 | verb_inflection _infl; |
308 | return new string_token(*this); | 139 | } _verb; |
309 | } | 140 | struct { |
141 | noun _noun; | ||
142 | noun_inflection _infl; | ||
143 | } _noun; | ||
144 | struct { | ||
145 | adjective _adjective; | ||
146 | adjective_inflection _infl; | ||
147 | } _adjective; | ||
148 | struct { | ||
149 | adverb _adverb; | ||
150 | adverb_inflection _infl; | ||
151 | } _adverb; | ||
152 | struct { | ||
153 | preposition _preposition; | ||
154 | } _preposition; | ||
155 | struct { | ||
156 | fillin_type _type; | ||
157 | } _fillin; | ||
158 | struct { | ||
159 | std::string _str; | ||
160 | } _string; | ||
161 | struct { | ||
162 | std::list<token> _utterance; | ||
163 | } _utterance; | ||
164 | }; | ||
310 | }; | 165 | }; |
311 | 166 | ||
312 | }; | 167 | }; |
313 | 168 | ||
314 | #endif /* end of include guard: TOKEN_H_AD62C505 */ | 169 | #endif /* end of include guard: TOKEN_H_AD62C505 */ |
diff --git a/lib/util.h b/lib/util.h index 815b47c..fb5fe67 100644 --- a/lib/util.h +++ b/lib/util.h | |||
@@ -1,10 +1,6 @@ | |||
1 | #ifndef UTIL_H_15DDCA2D | 1 | #ifndef UTIL_H_15DDCA2D |
2 | #define UTIL_H_15DDCA2D | 2 | #define UTIL_H_15DDCA2D |
3 | 3 | ||
4 | #include <string> | ||
5 | #include <iterator> | ||
6 | #include <sstream> | ||
7 | |||
8 | namespace verbly { | 4 | namespace verbly { |
9 | 5 | ||
10 | template <class InputIterator> | 6 | template <class InputIterator> |
@@ -32,7 +28,7 @@ namespace verbly { | |||
32 | 28 | ||
33 | while (!input.empty()) | 29 | while (!input.empty()) |
34 | { | 30 | { |
35 | int divider = input.find(" "); | 31 | int divider = input.find(delimiter); |
36 | if (divider == std::string::npos) | 32 | if (divider == std::string::npos) |
37 | { | 33 | { |
38 | result.push_back(input); | 34 | result.push_back(input); |
@@ -41,7 +37,7 @@ namespace verbly { | |||
41 | } else { | 37 | } else { |
42 | result.push_back(input.substr(0, divider)); | 38 | result.push_back(input.substr(0, divider)); |
43 | 39 | ||
44 | input = input.substr(divider+1); | 40 | input = input.substr(divider+delimiter.length()); |
45 | } | 41 | } |
46 | } | 42 | } |
47 | 43 | ||
diff --git a/lib/verb.cpp b/lib/verb.cpp index 23f7c92..1f45d53 100644 --- a/lib/verb.cpp +++ b/lib/verb.cpp | |||
@@ -2,6 +2,11 @@ | |||
2 | 2 | ||
3 | namespace verbly { | 3 | namespace verbly { |
4 | 4 | ||
5 | verb::verb() | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
5 | verb::verb(const data& _data, int _id) : word(_data, _id) | 10 | verb::verb(const data& _data, int _id) : word(_data, _id) |
6 | { | 11 | { |
7 | 12 | ||
@@ -9,185 +14,51 @@ namespace verbly { | |||
9 | 14 | ||
10 | std::string verb::base_form() const | 15 | std::string verb::base_form() const |
11 | { | 16 | { |
17 | assert(_valid == true); | ||
18 | |||
12 | return _infinitive; | 19 | return _infinitive; |
13 | } | 20 | } |
14 | 21 | ||
15 | std::string verb::infinitive_form() const | 22 | std::string verb::infinitive_form() const |
16 | { | 23 | { |
24 | assert(_valid == true); | ||
25 | |||
17 | return _infinitive; | 26 | return _infinitive; |
18 | } | 27 | } |
19 | 28 | ||
20 | std::string verb::past_tense_form() const | 29 | std::string verb::past_tense_form() const |
21 | { | 30 | { |
31 | assert(_valid == true); | ||
32 | |||
22 | return _past_tense; | 33 | return _past_tense; |
23 | } | 34 | } |
24 | 35 | ||
25 | std::string verb::past_participle_form() const | 36 | std::string verb::past_participle_form() const |
26 | { | 37 | { |
38 | assert(_valid == true); | ||
39 | |||
27 | return _past_participle; | 40 | return _past_participle; |
28 | } | 41 | } |
29 | 42 | ||
30 | std::string verb::ing_form() const | 43 | std::string verb::ing_form() const |
31 | { | 44 | { |
45 | assert(_valid == true); | ||
46 | |||
32 | return _ing_form; | 47 | return _ing_form; |
33 | } | 48 | } |
34 | 49 | ||
35 | std::string verb::s_form() const | 50 | std::string verb::s_form() const |
36 | { | 51 | { |
37 | return _s_form; | 52 | assert(_valid == true); |
38 | } | ||
39 | |||
40 | verb_query::verb_query(const data& _data) : _data(_data) | ||
41 | { | ||
42 | |||
43 | } | ||
44 | |||
45 | verb_query& verb_query::limit(int _limit) | ||
46 | { | ||
47 | if ((_limit > 0) || (_limit == unlimited)) | ||
48 | { | ||
49 | this->_limit = _limit; | ||
50 | } | ||
51 | |||
52 | return *this; | ||
53 | } | ||
54 | |||
55 | verb_query& verb_query::random(bool _random) | ||
56 | { | ||
57 | this->_random = _random; | ||
58 | |||
59 | return *this; | ||
60 | } | ||
61 | |||
62 | verb_query& verb_query::except(const verb& _word) | ||
63 | { | ||
64 | _except.push_back(_word); | ||
65 | |||
66 | return *this; | ||
67 | } | ||
68 | |||
69 | verb_query& verb_query::rhymes_with(const word& _word) | ||
70 | { | ||
71 | for (auto rhyme : _word.rhyme_phonemes()) | ||
72 | { | ||
73 | _rhymes.push_back(rhyme); | ||
74 | } | ||
75 | |||
76 | if (dynamic_cast<const verb*>(&_word) != nullptr) | ||
77 | { | ||
78 | _except.push_back(dynamic_cast<const verb&>(_word)); | ||
79 | } | ||
80 | 53 | ||
81 | return *this; | 54 | return _s_form; |
82 | } | 55 | } |
83 | 56 | ||
84 | verb_query& verb_query::has_pronunciation(bool _has_prn) | 57 | frame_query verb::frames() const |
85 | { | 58 | { |
86 | this->_has_prn = _has_prn; | 59 | assert(_valid == true); |
87 | 60 | ||
88 | return *this; | 61 | return _data->frames().for_verb(*this); |
89 | } | 62 | } |
90 | |||
91 | std::list<verb> verb_query::run() const | ||
92 | { | ||
93 | std::stringstream construct; | ||
94 | construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; | ||
95 | std::list<std::string> conditions; | ||
96 | |||
97 | if (_has_prn) | ||
98 | { | ||
99 | conditions.push_back("verb_id IN (SELECT verb_id FROM verb_pronunciations)"); | ||
100 | } | ||
101 | |||
102 | if (!_rhymes.empty()) | ||
103 | { | ||
104 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
105 | std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
106 | conditions.push_back(cond); | ||
107 | } | ||
108 | |||
109 | for (auto except : _except) | ||
110 | { | ||
111 | conditions.push_back("verb_id != @EXCID"); | ||
112 | } | ||
113 | 63 | ||
114 | if (!conditions.empty()) | ||
115 | { | ||
116 | construct << " WHERE "; | ||
117 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
118 | } | ||
119 | |||
120 | if (_random) | ||
121 | { | ||
122 | construct << " ORDER BY RANDOM()"; | ||
123 | } | ||
124 | |||
125 | if (_limit != unlimited) | ||
126 | { | ||
127 | construct << " LIMIT " << _limit; | ||
128 | } | ||
129 | |||
130 | sqlite3_stmt* ppstmt; | ||
131 | std::string query = construct.str(); | ||
132 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
133 | { | ||
134 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
135 | } | ||
136 | |||
137 | if (!_rhymes.empty()) | ||
138 | { | ||
139 | int i = 0; | ||
140 | for (auto rhyme : _rhymes) | ||
141 | { | ||
142 | std::string rhymer = "%" + rhyme; | ||
143 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
144 | |||
145 | i++; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | for (auto except : _except) | ||
150 | { | ||
151 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
152 | } | ||
153 | |||
154 | std::list<verb> output; | ||
155 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
156 | { | ||
157 | verb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
158 | tnc._infinitive = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
159 | tnc._past_tense = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
160 | tnc._past_participle = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
161 | tnc._ing_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
162 | tnc._s_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 5))); | ||
163 | |||
164 | output.push_back(tnc); | ||
165 | } | ||
166 | |||
167 | sqlite3_finalize(ppstmt); | ||
168 | |||
169 | for (auto& verb : output) | ||
170 | { | ||
171 | query = "SELECT pronunciation FROM verb_pronunciations WHERE verb_id = ?"; | ||
172 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
173 | { | ||
174 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
175 | } | ||
176 | |||
177 | sqlite3_bind_int(ppstmt, 1, verb._id); | ||
178 | |||
179 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
180 | { | ||
181 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
182 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
183 | |||
184 | verb.pronunciations.push_back(phonemes); | ||
185 | } | ||
186 | |||
187 | sqlite3_finalize(ppstmt); | ||
188 | } | ||
189 | |||
190 | return output; | ||
191 | } | ||
192 | |||
193 | }; | 64 | }; |
diff --git a/lib/verb.h b/lib/verb.h index 7cc87e2..7a2486e 100644 --- a/lib/verb.h +++ b/lib/verb.h | |||
@@ -3,26 +3,7 @@ | |||
3 | 3 | ||
4 | namespace verbly { | 4 | namespace verbly { |
5 | 5 | ||
6 | /*class frame_part { | 6 | class frame_query; |
7 | |||
8 | }; | ||
9 | |||
10 | class frame { | ||
11 | private: | ||
12 | std::list<frame_part> content; | ||
13 | std::map<std::string, std::vector<std::list<frame_part>::iterator>> predicates; | ||
14 | |||
15 | public: | ||
16 | frame(std::list<frame_part> content) : content(content) | ||
17 | { | ||
18 | |||
19 | } | ||
20 | |||
21 | std::unique_ptr<token> make_utterance() const | ||
22 | { | ||
23 | |||
24 | } | ||
25 | };*/ | ||
26 | 7 | ||
27 | class verb : public word { | 8 | class verb : public word { |
28 | private: | 9 | private: |
@@ -35,6 +16,7 @@ namespace verbly { | |||
35 | friend class verb_query; | 16 | friend class verb_query; |
36 | 17 | ||
37 | public: | 18 | public: |
19 | verb(); | ||
38 | verb(const data& _data, int _id); | 20 | verb(const data& _data, int _id); |
39 | 21 | ||
40 | std::string base_form() const; | 22 | std::string base_form() const; |
@@ -43,29 +25,8 @@ namespace verbly { | |||
43 | std::string past_participle_form() const; | 25 | std::string past_participle_form() const; |
44 | std::string ing_form() const; | 26 | std::string ing_form() const; |
45 | std::string s_form() const; | 27 | std::string s_form() const; |
46 | }; | ||
47 | |||
48 | class verb_query { | ||
49 | public: | ||
50 | verb_query(const data& _data); | ||
51 | |||
52 | verb_query& limit(int _limit); | ||
53 | verb_query& random(bool _random); | ||
54 | verb_query& except(const verb& _word); | ||
55 | verb_query& rhymes_with(const word& _word); | ||
56 | verb_query& has_pronunciation(bool _has_prn); | ||
57 | 28 | ||
58 | std::list<verb> run() const; | 29 | frame_query frames() const; |
59 | |||
60 | const static int unlimited = -1; | ||
61 | |||
62 | private: | ||
63 | const data& _data; | ||
64 | int _limit = unlimited; | ||
65 | bool _random = false; | ||
66 | std::list<std::string> _rhymes; | ||
67 | std::list<verb> _except; | ||
68 | bool _has_prn = false; | ||
69 | }; | 30 | }; |
70 | 31 | ||
71 | }; | 32 | }; |
diff --git a/lib/verb_query.cpp b/lib/verb_query.cpp new file mode 100644 index 0000000..173a04e --- /dev/null +++ b/lib/verb_query.cpp | |||
@@ -0,0 +1,170 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | verb_query::verb_query(const data& _data) : _data(_data) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | verb_query& verb_query::limit(int _limit) | ||
11 | { | ||
12 | if ((_limit > 0) || (_limit == unlimited)) | ||
13 | { | ||
14 | this->_limit = _limit; | ||
15 | } | ||
16 | |||
17 | return *this; | ||
18 | } | ||
19 | |||
20 | verb_query& verb_query::random() | ||
21 | { | ||
22 | this->_random = true; | ||
23 | |||
24 | return *this; | ||
25 | } | ||
26 | |||
27 | verb_query& verb_query::except(const verb& _word) | ||
28 | { | ||
29 | _except.push_back(_word); | ||
30 | |||
31 | return *this; | ||
32 | } | ||
33 | |||
34 | verb_query& verb_query::rhymes_with(const word& _word) | ||
35 | { | ||
36 | for (auto rhyme : _word.rhyme_phonemes()) | ||
37 | { | ||
38 | _rhymes.push_back(rhyme); | ||
39 | } | ||
40 | |||
41 | if (dynamic_cast<const verb*>(&_word) != nullptr) | ||
42 | { | ||
43 | _except.push_back(dynamic_cast<const verb&>(_word)); | ||
44 | } | ||
45 | |||
46 | return *this; | ||
47 | } | ||
48 | |||
49 | verb_query& verb_query::has_pronunciation() | ||
50 | { | ||
51 | this->_has_prn = true; | ||
52 | |||
53 | return *this; | ||
54 | } | ||
55 | |||
56 | verb_query& verb_query::has_frames() | ||
57 | { | ||
58 | this->_has_frames = true; | ||
59 | |||
60 | return *this; | ||
61 | } | ||
62 | |||
63 | std::list<verb> verb_query::run() const | ||
64 | { | ||
65 | std::stringstream construct; | ||
66 | construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; | ||
67 | std::list<std::string> conditions; | ||
68 | |||
69 | if (_has_prn) | ||
70 | { | ||
71 | conditions.push_back("verb_id IN (SELECT verb_id FROM verb_pronunciations)"); | ||
72 | } | ||
73 | |||
74 | if (!_rhymes.empty()) | ||
75 | { | ||
76 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
77 | std::string cond = "verb_id IN (SELECT verb_id FROM verb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
78 | conditions.push_back(cond); | ||
79 | } | ||
80 | |||
81 | for (auto except : _except) | ||
82 | { | ||
83 | conditions.push_back("verb_id != @EXCID"); | ||
84 | } | ||
85 | |||
86 | if (!_has_frames) | ||
87 | { | ||
88 | conditions.push_back("verb_id IN (SELECT verb_id FROM verb_groups)"); | ||
89 | } | ||
90 | |||
91 | if (!conditions.empty()) | ||
92 | { | ||
93 | construct << " WHERE "; | ||
94 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
95 | } | ||
96 | |||
97 | if (_random) | ||
98 | { | ||
99 | construct << " ORDER BY RANDOM()"; | ||
100 | } | ||
101 | |||
102 | if (_limit != unlimited) | ||
103 | { | ||
104 | construct << " LIMIT " << _limit; | ||
105 | } | ||
106 | |||
107 | sqlite3_stmt* ppstmt; | ||
108 | std::string query = construct.str(); | ||
109 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
110 | { | ||
111 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
112 | } | ||
113 | |||
114 | if (!_rhymes.empty()) | ||
115 | { | ||
116 | int i = 0; | ||
117 | for (auto rhyme : _rhymes) | ||
118 | { | ||
119 | std::string rhymer = "%" + rhyme; | ||
120 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
121 | |||
122 | i++; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | for (auto except : _except) | ||
127 | { | ||
128 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
129 | } | ||
130 | |||
131 | std::list<verb> output; | ||
132 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
133 | { | ||
134 | verb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
135 | tnc._infinitive = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
136 | tnc._past_tense = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
137 | tnc._past_participle = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
138 | tnc._ing_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
139 | tnc._s_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 5))); | ||
140 | |||
141 | output.push_back(tnc); | ||
142 | } | ||
143 | |||
144 | sqlite3_finalize(ppstmt); | ||
145 | |||
146 | for (auto& verb : output) | ||
147 | { | ||
148 | query = "SELECT pronunciation FROM verb_pronunciations WHERE verb_id = ?"; | ||
149 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
150 | { | ||
151 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
152 | } | ||
153 | |||
154 | sqlite3_bind_int(ppstmt, 1, verb._id); | ||
155 | |||
156 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
157 | { | ||
158 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
159 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
160 | |||
161 | verb.pronunciations.push_back(phonemes); | ||
162 | } | ||
163 | |||
164 | sqlite3_finalize(ppstmt); | ||
165 | } | ||
166 | |||
167 | return output; | ||
168 | } | ||
169 | |||
170 | }; | ||
diff --git a/lib/verb_query.h b/lib/verb_query.h new file mode 100644 index 0000000..24f5732 --- /dev/null +++ b/lib/verb_query.h | |||
@@ -0,0 +1,34 @@ | |||
1 | #ifndef VERB_QUERY_H_34E5A679 | ||
2 | #define VERB_QUERY_H_34E5A679 | ||
3 | |||
4 | namespace verbly { | ||
5 | |||
6 | class verb_query { | ||
7 | public: | ||
8 | verb_query(const data& _data); | ||
9 | |||
10 | verb_query& limit(int _limit); | ||
11 | verb_query& random(); | ||
12 | verb_query& except(const verb& _word); | ||
13 | verb_query& rhymes_with(const word& _word); | ||
14 | verb_query& has_pronunciation(); | ||
15 | |||
16 | verb_query& has_frames(); | ||
17 | |||
18 | std::list<verb> run() const; | ||
19 | |||
20 | const static int unlimited = -1; | ||
21 | |||
22 | private: | ||
23 | const data& _data; | ||
24 | int _limit = unlimited; | ||
25 | bool _random = false; | ||
26 | std::list<std::string> _rhymes; | ||
27 | std::list<verb> _except; | ||
28 | bool _has_prn = false; | ||
29 | bool _has_frames = false; | ||
30 | }; | ||
31 | |||
32 | }; | ||
33 | |||
34 | #endif /* end of include guard: VERB_QUERY_H_34E5A679 */ | ||
diff --git a/lib/verbly.h b/lib/verbly.h index b9f5367..cfaf5bc 100644 --- a/lib/verbly.h +++ b/lib/verbly.h | |||
@@ -1,14 +1,35 @@ | |||
1 | #ifndef VERBLY_H_5B39CE50 | 1 | #ifndef VERBLY_H_5B39CE50 |
2 | #define VERBLY_H_5B39CE50 | 2 | #define VERBLY_H_5B39CE50 |
3 | 3 | ||
4 | #include "c++14.h" | 4 | #include <string> |
5 | #include <list> | ||
6 | #include <sstream> | ||
7 | #include <algorithm> | ||
8 | #include <cassert> | ||
9 | #include <set> | ||
10 | #include <stdexcept> | ||
11 | #include <vector> | ||
12 | #include <map> | ||
13 | #include <iterator> | ||
14 | #include <sstream> | ||
15 | #include <functional> | ||
16 | #include <iostream> | ||
17 | #include <new> | ||
18 | |||
5 | #include "util.h" | 19 | #include "util.h" |
6 | #include "token.h" | ||
7 | #include "data.h" | 20 | #include "data.h" |
8 | #include "word.h" | 21 | #include "word.h" |
9 | #include "verb.h" | 22 | #include "verb.h" |
10 | #include "adverb.h" | 23 | #include "adverb.h" |
11 | #include "adjective.h" | 24 | #include "adjective.h" |
12 | #include "noun.h" | 25 | #include "noun.h" |
26 | #include "frame.h" | ||
27 | #include "preposition.h" | ||
28 | #include "token.h" | ||
29 | #include "noun_query.h" | ||
30 | #include "adverb_query.h" | ||
31 | #include "adjective_query.h" | ||
32 | #include "verb_query.h" | ||
33 | #include "frame_query.h" | ||
13 | 34 | ||
14 | #endif /* end of include guard: VERBLY_H_5B39CE50 */ | 35 | #endif /* end of include guard: VERBLY_H_5B39CE50 */ |
diff --git a/lib/word.cpp b/lib/word.cpp index 15af150..13c611f 100644 --- a/lib/word.cpp +++ b/lib/word.cpp | |||
@@ -3,13 +3,20 @@ | |||
3 | 3 | ||
4 | namespace verbly { | 4 | namespace verbly { |
5 | 5 | ||
6 | word::word(const data& _data, int _id) : _data(_data), _id(_id) | 6 | word::word() |
7 | { | ||
8 | |||
9 | } | ||
10 | |||
11 | word::word(const data& _data, int _id) : _data(&_data), _id(_id), _valid(true) | ||
7 | { | 12 | { |
8 | 13 | ||
9 | } | 14 | } |
10 | 15 | ||
11 | std::list<std::string> word::rhyme_phonemes() const | 16 | std::list<std::string> word::rhyme_phonemes() const |
12 | { | 17 | { |
18 | assert(_valid == true); | ||
19 | |||
13 | std::list<std::string> result; | 20 | std::list<std::string> result; |
14 | 21 | ||
15 | for (auto pronunciation : pronunciations) | 22 | for (auto pronunciation : pronunciations) |
@@ -32,6 +39,8 @@ namespace verbly { | |||
32 | 39 | ||
33 | bool word::starts_with_vowel_sound() const | 40 | bool word::starts_with_vowel_sound() const |
34 | { | 41 | { |
42 | assert(_valid == true); | ||
43 | |||
35 | if (pronunciations.size() > 0) | 44 | if (pronunciations.size() > 0) |
36 | { | 45 | { |
37 | return std::any_of(std::begin(pronunciations), std::end(pronunciations), [] (std::list<std::string> phonemes) { | 46 | return std::any_of(std::begin(pronunciations), std::end(pronunciations), [] (std::list<std::string> phonemes) { |
diff --git a/lib/word.h b/lib/word.h index db3242a..dc6fac8 100644 --- a/lib/word.h +++ b/lib/word.h | |||
@@ -3,26 +3,23 @@ | |||
3 | 3 | ||
4 | namespace verbly { | 4 | namespace verbly { |
5 | 5 | ||
6 | class adjective_query; | ||
7 | class verb_query; | ||
8 | class adverb_query; | ||
9 | |||
10 | template <class T> | ||
11 | class query; | ||
12 | |||
13 | class word { | 6 | class word { |
14 | protected: | 7 | protected: |
15 | const data& _data; | 8 | const data* _data; |
16 | int _id; | 9 | int _id; |
10 | bool _valid = false; | ||
17 | 11 | ||
18 | std::list<std::list<std::string>> pronunciations; | 12 | std::list<std::list<std::string>> pronunciations; |
19 | 13 | ||
14 | word(); | ||
20 | word(const data& _data, int _id); | 15 | word(const data& _data, int _id); |
21 | 16 | ||
22 | friend class adjective_query; | 17 | friend class adjective_query; |
23 | friend class verb_query; | 18 | friend class verb_query; |
24 | friend class noun_query; | 19 | friend class noun_query; |
25 | friend class adverb_query; | 20 | friend class adverb_query; |
21 | friend class frame_query; | ||
22 | friend class preposition_query; | ||
26 | 23 | ||
27 | public: | 24 | public: |
28 | virtual std::string base_form() const = 0; | 25 | virtual std::string base_form() const = 0; |