summary refs log tree commit diff stats
path: root/lib/adverb.cpp
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2016-03-24 23:16:07 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2016-03-24 23:16:07 -0400
commiteef5de613c75661e5d94baa086f6f2ddc26c7ed0 (patch)
tree180230f6a245c5bca94d894273f5d2b93ded3f04 /lib/adverb.cpp
parentd5ee4e39e5b5b3b8daa85cd972802195ad35e965 (diff)
downloadverbly-eef5de613c75661e5d94baa086f6f2ddc26c7ed0.tar.gz
verbly-eef5de613c75661e5d94baa086f6f2ddc26c7ed0.tar.bz2
verbly-eef5de613c75661e5d94baa086f6f2ddc26c7ed0.zip
Added verb frames
In addition:
- Added prepositions.
- Rewrote a lot of the query interface. It now, for a lot of relationships, supports nested AND, OR, and NOT logic.
- Rewrote the token class. It is now a union-like class instead of being polymorphic, which means smart pointers are no longer necessary.
- Querying with regards to word derivation has been temporarily removed.
- Sentinel values are now supported for all word types.
- The VerbNet data retrieved from http://verbs.colorado.edu/~mpalmer/projects/verbnet/downloads.html was found to not be perfectly satisfactory in some regards, especially regarding adjective phrases. A patch file is now included in the repository describing the changes made to the VerbNet v3.2 download for the canonical verbly datafile.
Diffstat (limited to 'lib/adverb.cpp')
-rw-r--r--lib/adverb.cpp443
1 files changed, 23 insertions, 420 deletions
diff --git a/lib/adverb.cpp b/lib/adverb.cpp index 8fcddad..442574e 100644 --- a/lib/adverb.cpp +++ b/lib/adverb.cpp
@@ -2,6 +2,11 @@
2 2
3namespace verbly { 3namespace verbly {
4 4
5 adverb::adverb()
6 {
7
8 }
9
5 adverb::adverb(const data& _data, int _id) : word(_data, _id) 10 adverb::adverb(const data& _data, int _id) : word(_data, _id)
6 { 11 {
7 12
@@ -9,460 +14,58 @@ namespace verbly {
9 14
10 std::string adverb::base_form() const 15 std::string adverb::base_form() const
11 { 16 {
17 assert(_valid == true);
18
12 return _base_form; 19 return _base_form;
13 } 20 }
14 21
15 std::string adverb::comparative_form() const 22 std::string adverb::comparative_form() const
16 { 23 {
24 assert(_valid == true);
25
17 return _comparative_form; 26 return _comparative_form;
18 } 27 }
19 28
20 std::string adverb::superlative_form() const 29 std::string adverb::superlative_form() const
21 { 30 {
31 assert(_valid == true);
32
22 return _superlative_form; 33 return _superlative_form;
23 } 34 }
24 35
25 bool adverb::has_comparative_form() const 36 bool adverb::has_comparative_form() const
26 { 37 {
38 assert(_valid == true);
39
27 return !_comparative_form.empty(); 40 return !_comparative_form.empty();
28 } 41 }
29 42
30 bool adverb::has_superlative_form() const 43 bool adverb::has_superlative_form() const
31 { 44 {
45 assert(_valid == true);
46
32 return !_superlative_form.empty(); 47 return !_superlative_form.empty();
33 } 48 }
34 49
35 adverb_query adverb::antonyms() const 50 adverb_query adverb::antonyms() const
36 { 51 {
37 return _data.adverbs().antonym_of(*this); 52 assert(_valid == true);
38 }
39
40 adverb_query adverb::synonyms() const
41 {
42 return _data.adverbs().synonym_of(*this);
43 }
44
45 adjective_query adverb::anti_mannernyms() const
46 {
47 return _data.adjectives().anti_mannernym_of(*this);
48 }
49
50 adverb_query::adverb_query(const data& _data) : _data(_data)
51 {
52
53 }
54
55 adverb_query& adverb_query::limit(int _limit)
56 {
57 if ((_limit > 0) || (_limit == unlimited))
58 {
59 this->_limit = _limit;
60 }
61
62 return *this;
63 }
64
65 adverb_query& adverb_query::random(bool _random)
66 {
67 this->_random = _random;
68
69 return *this;
70 }
71
72 adverb_query& adverb_query::except(const adverb& _word)
73 {
74 _except.push_back(_word);
75 53
76 return *this; 54 return _data->adverbs().antonym_of(*this);
77 } 55 }
78 56
79 adverb_query& adverb_query::rhymes_with(const word& _word) 57 adverb_query adverb::synonyms() const
80 {
81 for (auto rhyme : _word.rhyme_phonemes())
82 {
83 _rhymes.push_back(rhyme);
84 }
85
86 if (dynamic_cast<const adverb*>(&_word) != nullptr)
87 {
88 _except.push_back(dynamic_cast<const adverb&>(_word));
89 }
90
91 return *this;
92 }
93
94 adverb_query& adverb_query::has_pronunciation(bool _has_prn)
95 {
96 this->_has_prn = _has_prn;
97
98 return *this;
99 }
100
101 adverb_query& adverb_query::requires_comparative_form(bool _arg)
102 {
103 _requires_comparative_form = _arg;
104
105 return *this;
106 }
107
108 adverb_query& adverb_query::requires_superlative_form(bool _arg)
109 {
110 _requires_superlative_form = _arg;
111
112 return *this;
113 }
114
115 adverb_query& adverb_query::has_antonyms(bool _arg)
116 {
117 _has_antonyms = _arg;
118
119 return *this;
120 }
121
122 adverb_query& adverb_query::antonym_of(const adverb& _adv)
123 {
124 _antonym_of.push_back(_adv);
125
126 return *this;
127 }
128
129 adverb_query& adverb_query::not_antonym_of(const adverb& _adv)
130 {
131 _not_antonym_of.push_back(_adv);
132
133 return *this;
134 }
135
136 adverb_query& adverb_query::has_synonyms(bool _arg)
137 {
138 _has_synonyms = _arg;
139
140 return *this;
141 }
142
143 adverb_query& adverb_query::synonym_of(const adverb& _adv)
144 {
145 _synonym_of.push_back(_adv);
146
147 return *this;
148 }
149
150 adverb_query& adverb_query::not_synonym_of(const adverb& _adv)
151 {
152 _not_synonym_of.push_back(_adv);
153
154 return *this;
155 }
156
157 adverb_query& adverb_query::is_mannernymic(bool _arg)
158 {
159 _is_mannernymic = _arg;
160
161 return *this;
162 }
163
164 adverb_query& adverb_query::mannernym_of(const adjective& _adj)
165 {
166 _mannernym_of.push_back(_adj);
167
168 return *this;
169 }
170
171 adverb_query& adverb_query::derived_from(const word& _w)
172 {
173 if (dynamic_cast<const adjective*>(&_w) != nullptr)
174 {
175 _derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w));
176 } else if (dynamic_cast<const adverb*>(&_w) != nullptr)
177 {
178 _derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w));
179 } else if (dynamic_cast<const noun*>(&_w) != nullptr)
180 {
181 _derived_from_noun.push_back(dynamic_cast<const noun&>(_w));
182 }
183
184 return *this;
185 }
186
187 adverb_query& adverb_query::not_derived_from(const word& _w)
188 { 58 {
189 if (dynamic_cast<const adjective*>(&_w) != nullptr) 59 assert(_valid == true);
190 {
191 _not_derived_from_adjective.push_back(dynamic_cast<const adjective&>(_w));
192 } else if (dynamic_cast<const adverb*>(&_w) != nullptr)
193 {
194 _not_derived_from_adverb.push_back(dynamic_cast<const adverb&>(_w));
195 } else if (dynamic_cast<const noun*>(&_w) != nullptr)
196 {
197 _not_derived_from_noun.push_back(dynamic_cast<const noun&>(_w));
198 }
199 60
200 return *this; 61 return _data->adverbs().synonym_of(*this);
201 } 62 }
202 63
203 std::list<adverb> adverb_query::run() const 64 adjective_query adverb::anti_mannernyms() const
204 { 65 {
205 std::stringstream construct; 66 assert(_valid == true);
206 construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs";
207 std::list<std::string> conditions;
208
209 if (_has_prn)
210 {
211 conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)");
212 }
213
214 if (!_rhymes.empty())
215 {
216 std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN");
217 std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
218 conditions.push_back(cond);
219 }
220
221 for (auto except : _except)
222 {
223 conditions.push_back("adverb_id != @EXCID");
224 }
225
226 if (_requires_comparative_form)
227 {
228 conditions.push_back("comparative IS NOT NULL");
229 }
230
231 if (_requires_superlative_form)
232 {
233 conditions.push_back("superlative IS NOT NULL");
234 }
235
236 if (_has_antonyms)
237 {
238 conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)");
239 }
240
241 if (!_antonym_of.empty())
242 {
243 std::list<std::string> clauses(_antonym_of.size(), "adverb_1_id = @ANTID");
244 std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
245 conditions.push_back(cond);
246 }
247
248 if (!_not_antonym_of.empty())
249 {
250 std::list<std::string> clauses(_not_antonym_of.size(), "adverb_1_id = @NANTID");
251 std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
252 conditions.push_back(cond);
253 }
254
255 if (_has_synonyms)
256 {
257 conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)");
258 }
259 67
260 if (!_synonym_of.empty()) 68 return _data->adjectives().anti_mannernym_of(*this);
261 {
262 std::list<std::string> clauses(_synonym_of.size(), "adverb_1_id = @SYNID");
263 std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
264 conditions.push_back(cond);
265 }
266
267 if (!_not_synonym_of.empty())
268 {
269 std::list<std::string> clauses(_not_synonym_of.size(), "adverb_1_id = @NSYNID");
270 std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
271 conditions.push_back(cond);
272 }
273
274 if (_is_mannernymic)
275 {
276 conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)");
277 }
278
279 if (!_mannernym_of.empty())
280 {
281 std::list<std::string> clauses(_mannernym_of.size(), "adjective_id = @AMANID");
282 std::string cond = "adverb_id IN (SELECT mannernym_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
283 conditions.push_back(cond);
284 }
285
286 if (!_derived_from_adjective.empty())
287 {
288 std::list<std::string> clauses(_derived_from_adjective.size(), "adjective_id = @DERADJ");
289 std::string cond = "adverb_id IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
290 conditions.push_back(cond);
291 }
292
293 if (!_not_derived_from_adjective.empty())
294 {
295 std::list<std::string> clauses(_not_derived_from_adjective.size(), "adjective_id = @NDERADJ");
296 std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM adjective_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
297 conditions.push_back(cond);
298 }
299
300 if (!_derived_from_adverb.empty())
301 {
302 std::list<std::string> clauses(_derived_from_adverb.size(), "adverb_2_id = @DERADV");
303 std::string cond = "adverb_id IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
304 conditions.push_back(cond);
305 }
306
307 if (!_not_derived_from_adverb.empty())
308 {
309 std::list<std::string> clauses(_not_derived_from_adverb.size(), "adverb_2_id = @NDERADV");
310 std::string cond = "adverb_id NOT IN (SELECT adverb_1_id FROM adverb_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
311 conditions.push_back(cond);
312 }
313
314 if (!_derived_from_noun.empty())
315 {
316 std::list<std::string> clauses(_derived_from_noun.size(), "noun_id = @DERN");
317 std::string cond = "adverb_id IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
318 conditions.push_back(cond);
319 }
320
321 if (!_not_derived_from_noun.empty())
322 {
323 std::list<std::string> clauses(_not_derived_from_noun.size(), "noun_id = @NDERN");
324 std::string cond = "adverb_id NOT IN (SELECT adverb_id FROM noun_adverb_derivation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")";
325 conditions.push_back(cond);
326 }
327
328 if (!conditions.empty())
329 {
330 construct << " WHERE ";
331 construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND ");
332 }
333
334 if (_random)
335 {
336 construct << " ORDER BY RANDOM()";
337 }
338
339 if (_limit != unlimited)
340 {
341 construct << " LIMIT " << _limit;
342 }
343
344 sqlite3_stmt* ppstmt;
345 std::string query = construct.str();
346 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
347 {
348 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
349 }
350
351 if (!_rhymes.empty())
352 {
353 int i = 0;
354 for (auto rhyme : _rhymes)
355 {
356 std::string rhymer = "%" + rhyme;
357 sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC);
358
359 i++;
360 }
361 }
362
363 for (auto except : _except)
364 {
365 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id);
366 }
367
368 for (auto antonym : _antonym_of)
369 {
370 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id);
371 }
372
373 for (auto antonym : _not_antonym_of)
374 {
375 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id);
376 }
377
378 for (auto synonym : _synonym_of)
379 {
380 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id);
381 }
382
383 for (auto synonym : _not_synonym_of)
384 {
385 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id);
386 }
387
388 for (auto adj : _mannernym_of)
389 {
390 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@AMANID"), adj._id);
391 }
392
393 for (auto adj : _derived_from_adjective)
394 {
395 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADJ"), adj._id);
396 }
397
398 for (auto adj : _not_derived_from_adjective)
399 {
400 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADJ"), adj._id);
401 }
402
403 for (auto adv : _derived_from_adverb)
404 {
405 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERADV"), adv._id);
406 }
407
408 for (auto adv : _not_derived_from_adverb)
409 {
410 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERADV"), adv._id);
411 }
412
413 for (auto n : _derived_from_noun)
414 {
415 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@DERN"), n._id);
416 }
417
418 for (auto n : _not_derived_from_noun)
419 {
420 sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NDERN"), n._id);
421 }
422
423 std::list<adverb> output;
424 while (sqlite3_step(ppstmt) == SQLITE_ROW)
425 {
426 adverb tnc {_data, sqlite3_column_int(ppstmt, 0)};
427 tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1)));
428
429 if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL)
430 {
431 tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2)));
432 }
433
434 if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL)
435 {
436 tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3)));
437 }
438
439 output.push_back(tnc);
440 }
441
442 sqlite3_finalize(ppstmt);
443
444 for (auto& adverb : output)
445 {
446 query = "SELECT pronunciation FROM adverb_pronunciations WHERE adverb_id = ?";
447 if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
448 {
449 throw std::runtime_error(sqlite3_errmsg(_data.ppdb));
450 }
451
452 sqlite3_bind_int(ppstmt, 1, adverb._id);
453
454 while (sqlite3_step(ppstmt) == SQLITE_ROW)
455 {
456 std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0)));
457 auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " ");
458
459 adverb.pronunciations.push_back(phonemes);
460 }
461
462 sqlite3_finalize(ppstmt);
463 }
464
465 return output;
466 } 69 }
467 70
468}; 71};