diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-03-16 11:27:16 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-03-16 11:27:16 -0400 |
commit | 3aceae8ab1eb5992110ea57a9479bbc3177feb21 (patch) | |
tree | 13167a266805344efb7bb1d900486f782c23285e | |
parent | e1be2716746e75cf6ed37e86461a7f580a964564 (diff) | |
download | furries-3aceae8ab1eb5992110ea57a9479bbc3177feb21.tar.gz furries-3aceae8ab1eb5992110ea57a9479bbc3177feb21.tar.bz2 furries-3aceae8ab1eb5992110ea57a9479bbc3177feb21.zip |
Added more inflections, word relationships, and pronunciations
Nouns, adjectives, and adverbs now have inflected forms. A large number of WordNet word relationships (all noun-noun relationships, plus synonymy and antonymy for all word types except verbs) have been added. Additionally, CMUDICT is now being used to store word pronunciations for rhyming purposes. Verbly is now also a compiled library rather than being header-only due to the complexity of the query interface.
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | furries.cpp | 16 | ||||
-rw-r--r-- | generator.cpp | 1303 | ||||
-rw-r--r-- | progress.h | 50 | ||||
-rw-r--r-- | schema.sql | 59 | ||||
-rw-r--r-- | verbly/adjective.cpp | 586 | ||||
-rw-r--r-- | verbly/adjective.h | 126 | ||||
-rw-r--r-- | verbly/adverb.cpp | 364 | ||||
-rw-r--r-- | verbly/adverb.h | 75 | ||||
-rw-r--r-- | verbly/data.cpp | 50 | ||||
-rw-r--r-- | verbly/data.h | 275 | ||||
-rw-r--r-- | verbly/noun.cpp | 916 | ||||
-rw-r--r-- | verbly/noun.h | 171 | ||||
-rw-r--r-- | verbly/token.cpp | 53 | ||||
-rw-r--r-- | verbly/token.h | 82 | ||||
-rw-r--r-- | verbly/util.h | 53 | ||||
-rw-r--r-- | verbly/verb.cpp | 193 | ||||
-rw-r--r-- | verbly/verb.h | 68 | ||||
-rw-r--r-- | verbly/verbly.h | 7 | ||||
-rw-r--r-- | verbly/word.cpp | 32 | ||||
-rw-r--r-- | verbly/word.h | 35 |
21 files changed, 4043 insertions, 477 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b6d991..3a884b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -8,11 +8,15 @@ pkg_check_modules(YamlCpp yaml-cpp REQUIRED) | |||
8 | pkg_check_modules(sqlite3 sqlite3 REQUIRED) | 8 | pkg_check_modules(sqlite3 sqlite3 REQUIRED) |
9 | find_package(libxml2 REQUIRED) | 9 | find_package(libxml2 REQUIRED) |
10 | 10 | ||
11 | add_library(verbly verbly/data.cpp verbly/adjective.cpp verbly/noun.cpp verbly/verb.cpp verbly/adverb.cpp verbly/token.cpp verbly/word.cpp) | ||
12 | set_property(TARGET verbly PROPERTY CXX_STANDARD 11) | ||
13 | set_property(TARGET verbly PROPERTY CXX_STANDARD_REQUIRED ON) | ||
14 | |||
11 | include_directories(vendor/twitcurl/libtwitcurl ${LIBXML2_INCLUDE_DIR} ${sqlite3_INCLUDE_DIR}) | 15 | include_directories(vendor/twitcurl/libtwitcurl ${LIBXML2_INCLUDE_DIR} ${sqlite3_INCLUDE_DIR}) |
12 | add_executable(furries furries.cpp) | 16 | add_executable(furries furries.cpp) |
13 | set_property(TARGET furries PROPERTY CXX_STANDARD 11) | 17 | set_property(TARGET furries PROPERTY CXX_STANDARD 11) |
14 | set_property(TARGET furries PROPERTY CXX_STANDARD_REQUIRED ON) | 18 | set_property(TARGET furries PROPERTY CXX_STANDARD_REQUIRED ON) |
15 | target_link_libraries(furries ${sqlite3_LIBRARIES} ${YamlCpp_LIBRARIES} twitcurl curl) | 19 | target_link_libraries(furries ${sqlite3_LIBRARIES} ${YamlCpp_LIBRARIES} twitcurl curl verbly) |
16 | 20 | ||
17 | add_executable(generator generator.cpp) | 21 | add_executable(generator generator.cpp) |
18 | set_property(TARGET generator PROPERTY CXX_STANDARD 11) | 22 | set_property(TARGET generator PROPERTY CXX_STANDARD 11) |
diff --git a/furries.cpp b/furries.cpp index 0cce8bd..55dfb7b 100644 --- a/furries.cpp +++ b/furries.cpp | |||
@@ -20,7 +20,7 @@ class fill_blanks { | |||
20 | { | 20 | { |
21 | switch (it->token_type()) | 21 | switch (it->token_type()) |
22 | { | 22 | { |
23 | case verbly::type::utterance: | 23 | case verbly::token::type::utterance: |
24 | { | 24 | { |
25 | auto& action = *dynamic_cast<verbly::utterance_token*>(it.get()); | 25 | auto& action = *dynamic_cast<verbly::utterance_token*>(it.get()); |
26 | for (auto& tkn : action) | 26 | for (auto& tkn : action) |
@@ -36,14 +36,14 @@ class fill_blanks { | |||
36 | break; | 36 | break; |
37 | } | 37 | } |
38 | 38 | ||
39 | case verbly::type::fillin: | 39 | case verbly::token::type::fillin: |
40 | { | 40 | { |
41 | auto& tkn = *dynamic_cast<verbly::fillin_token*>(it.get()); | 41 | auto& tkn = *dynamic_cast<verbly::fillin_token*>(it.get()); |
42 | switch (tkn.fillin_type()) | 42 | switch (tkn.fillin_type()) |
43 | { | 43 | { |
44 | case verbly::fillin_type::participle_phrase: | 44 | case verbly::fillin_type::participle_phrase: |
45 | { | 45 | { |
46 | const verbly::verb& v = database.verbs().random(true).limit(1).run().front(); | 46 | verbly::verb v = database.verbs().random(true).limit(1).run().front(); |
47 | /*verbly::utterance_token phrase = verbly::random(v.frames).make_utterance(); | 47 | /*verbly::utterance_token phrase = verbly::random(v.frames).make_utterance(); |
48 | while (std::begin(phrase)->token_type() != verbly::type::verb) | 48 | while (std::begin(phrase)->token_type() != verbly::type::verb) |
49 | { | 49 | { |
@@ -53,7 +53,7 @@ class fill_blanks { | |||
53 | *std::begin(phrase) = verbly::verb_token(v).conjugate(verbly::conjugation::present_participle); | 53 | *std::begin(phrase) = verbly::verb_token(v).conjugate(verbly::conjugation::present_participle); |
54 | *it = phrase;*/ | 54 | *it = phrase;*/ |
55 | auto avt = std::make_unique<verbly::verb_token>(v); | 55 | auto avt = std::make_unique<verbly::verb_token>(v); |
56 | avt->conjugate(verbly::conjugation::present_participle); | 56 | avt->inflect(verbly::verb_token::inflection::ing_form); |
57 | it = std::move(avt); | 57 | it = std::move(avt); |
58 | 58 | ||
59 | break; | 59 | break; |
@@ -61,16 +61,16 @@ class fill_blanks { | |||
61 | 61 | ||
62 | case verbly::fillin_type::adjective: | 62 | case verbly::fillin_type::adjective: |
63 | { | 63 | { |
64 | const verbly::adjective& adj = database.adjectives().random(true).limit(1).run().front(); | 64 | verbly::adjective adj = database.adjectives().random(true).limit(1).run().front(); |
65 | it = std::make_unique<verbly::string_token>(adj.form); | 65 | it = std::make_unique<verbly::string_token>(adj.base_form()); |
66 | 66 | ||
67 | break; | 67 | break; |
68 | } | 68 | } |
69 | 69 | ||
70 | case verbly::fillin_type::adverb: | 70 | case verbly::fillin_type::adverb: |
71 | { | 71 | { |
72 | const verbly::adverb& adv = database.adverbs().random(true).limit(1).run().front(); | 72 | verbly::adverb adv = database.adverbs().random(true).limit(1).run().front(); |
73 | it = std::make_unique<verbly::string_token>(adv.form); | 73 | it = std::make_unique<verbly::string_token>(adv.base_form()); |
74 | 74 | ||
75 | break; | 75 | break; |
76 | } | 76 | } |
diff --git a/generator.cpp b/generator.cpp index c389963..305d121 100644 --- a/generator.cpp +++ b/generator.cpp | |||
@@ -9,6 +9,8 @@ | |||
9 | #include <sqlite3.h> | 9 | #include <sqlite3.h> |
10 | #include <sstream> | 10 | #include <sstream> |
11 | #include <regex> | 11 | #include <regex> |
12 | #include <list> | ||
13 | #include "progress.h" | ||
12 | 14 | ||
13 | struct verb { | 15 | struct verb { |
14 | std::string infinitive; | 16 | std::string infinitive; |
@@ -18,6 +20,17 @@ struct verb { | |||
18 | std::string s_form; | 20 | std::string s_form; |
19 | }; | 21 | }; |
20 | 22 | ||
23 | struct adjective { | ||
24 | std::string base; | ||
25 | std::string comparative; | ||
26 | std::string superlative; | ||
27 | }; | ||
28 | |||
29 | struct noun { | ||
30 | std::string singular; | ||
31 | std::string plural; | ||
32 | }; | ||
33 | |||
21 | struct group { | 34 | struct group { |
22 | std::string id; | 35 | std::string id; |
23 | std::set<std::string> members; | 36 | std::set<std::string> members; |
@@ -25,21 +38,33 @@ struct group { | |||
25 | 38 | ||
26 | std::map<std::string, group> groups; | 39 | std::map<std::string, group> groups; |
27 | std::map<std::string, verb> verbs; | 40 | std::map<std::string, verb> verbs; |
41 | std::map<std::string, adjective> adjectives; | ||
42 | std::map<std::string, noun> nouns; | ||
28 | std::map<int, std::map<int, int>> wn; | 43 | std::map<int, std::map<int, int>> wn; |
44 | std::map<std::string, std::set<std::string>> pronunciations; | ||
29 | 45 | ||
30 | void print_usage() | 46 | void print_usage() |
31 | { | 47 | { |
32 | std::cout << "Verbly Datafile Generator" << std::endl; | 48 | std::cout << "Verbly Datafile Generator" << std::endl; |
33 | std::cout << "-------------------------" << std::endl; | 49 | std::cout << "-------------------------" << std::endl; |
34 | std::cout << "Requires exactly four arguments." << std::endl; | 50 | std::cout << "Requires exactly six arguments." << std::endl; |
35 | std::cout << "1. The path to a VerbNet data directory." << std::endl; | 51 | std::cout << "1. The path to a VerbNet data directory." << std::endl; |
36 | std::cout << "2. The path to a SemLink vnpbMappings file." << std::endl; | 52 | std::cout << "2. The path to a SemLink vnpbMappings file." << std::endl; |
37 | std::cout << "3. The path to an AGID infl.txt file." << std::endl; | 53 | std::cout << "3. The path to an AGID infl.txt file." << std::endl; |
38 | std::cout << "4. The path to a WordNet prolog data directory." << std::endl; | 54 | std::cout << "4. The path to a WordNet prolog data directory." << std::endl; |
39 | std::cout << "5. Datafile output path." << std::endl; | 55 | std::cout << "5. The path to a CMUDICT pronunciation file." << std::endl; |
56 | std::cout << "6. Datafile output path." << std::endl; | ||
40 | 57 | ||
41 | exit(1); | 58 | exit(1); |
42 | } | 59 | } |
60 | |||
61 | void db_error(sqlite3* ppdb, std::string) | ||
62 | { | ||
63 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | ||
64 | sqlite3_close_v2(ppdb); | ||
65 | print_usage(); | ||
66 | } | ||
67 | |||
43 | /* | 68 | /* |
44 | void parse_group(xmlNodePtr top, std::string filename) | 69 | void parse_group(xmlNodePtr top, std::string filename) |
45 | { | 70 | { |
@@ -87,7 +112,7 @@ void parse_group(xmlNodePtr top, std::string filename) | |||
87 | 112 | ||
88 | int main(int argc, char** argv) | 113 | int main(int argc, char** argv) |
89 | { | 114 | { |
90 | if (argc != 6) | 115 | if (argc != 7) |
91 | { | 116 | { |
92 | print_usage(); | 117 | print_usage(); |
93 | } | 118 | } |
@@ -137,7 +162,7 @@ int main(int argc, char** argv) | |||
137 | closedir(dir);*/ | 162 | closedir(dir);*/ |
138 | 163 | ||
139 | // Get verbs from AGID | 164 | // Get verbs from AGID |
140 | std::cout << "Reading verb inflection..." << std::endl; | 165 | std::cout << "Reading inflections..." << std::endl; |
141 | 166 | ||
142 | std::ifstream agidfile(argv[3]); | 167 | std::ifstream agidfile(argv[3]); |
143 | if (!agidfile.is_open()) | 168 | if (!agidfile.is_open()) |
@@ -162,11 +187,7 @@ int main(int argc, char** argv) | |||
162 | int divider = line.find_first_of(" "); | 187 | int divider = line.find_first_of(" "); |
163 | std::string word = line.substr(0, divider); | 188 | std::string word = line.substr(0, divider); |
164 | line = line.substr(divider+1); | 189 | line = line.substr(divider+1); |
165 | 190 | char type = line[0]; | |
166 | if (line[0] != 'V') | ||
167 | { | ||
168 | continue; | ||
169 | } | ||
170 | 191 | ||
171 | if (line[1] == '?') | 192 | if (line[1] == '?') |
172 | { | 193 | { |
@@ -174,7 +195,7 @@ int main(int argc, char** argv) | |||
174 | } else { | 195 | } else { |
175 | line.erase(0, 3); | 196 | line.erase(0, 3); |
176 | } | 197 | } |
177 | 198 | ||
178 | std::vector<std::string> forms; | 199 | std::vector<std::string> forms; |
179 | while (!line.empty()) | 200 | while (!line.empty()) |
180 | { | 201 | { |
@@ -187,52 +208,129 @@ int main(int argc, char** argv) | |||
187 | inflection = line; | 208 | inflection = line; |
188 | line = ""; | 209 | line = ""; |
189 | } | 210 | } |
190 | 211 | ||
191 | if ((divider = inflection.find_first_of(",?")) != std::string::npos) | 212 | if ((divider = inflection.find_first_of(",?")) != std::string::npos) |
192 | { | 213 | { |
193 | inflection = inflection.substr(0, divider); | 214 | inflection = inflection.substr(0, divider); |
194 | } | 215 | } |
195 | 216 | ||
196 | forms.push_back(inflection); | 217 | forms.push_back(inflection); |
197 | } | 218 | } |
198 | 219 | ||
199 | verb v; | 220 | switch (type) |
200 | v.infinitive = word; | ||
201 | if (forms.size() == 4) | ||
202 | { | 221 | { |
203 | v.past_tense = forms[0]; | 222 | case 'V': |
204 | v.past_participle = forms[1]; | 223 | { |
205 | v.ing_form = forms[2]; | 224 | verb v; |
206 | v.s_form = forms[3]; | 225 | v.infinitive = word; |
207 | } else if (forms.size() == 3) | 226 | if (forms.size() == 4) |
227 | { | ||
228 | v.past_tense = forms[0]; | ||
229 | v.past_participle = forms[1]; | ||
230 | v.ing_form = forms[2]; | ||
231 | v.s_form = forms[3]; | ||
232 | } else if (forms.size() == 3) | ||
233 | { | ||
234 | v.past_tense = forms[0]; | ||
235 | v.past_participle = forms[0]; | ||
236 | v.ing_form = forms[1]; | ||
237 | v.s_form = forms[2]; | ||
238 | } else if (forms.size() == 8) | ||
239 | { | ||
240 | // As of AGID 2014.08.11, this is only "to be" | ||
241 | v.past_tense = forms[0]; | ||
242 | v.past_participle = forms[2]; | ||
243 | v.ing_form = forms[3]; | ||
244 | v.s_form = forms[4]; | ||
245 | } else { | ||
246 | // Words that don't fit the cases above as of AGID 2014.08.11: | ||
247 | // - may and shall do not conjugate the way we want them to | ||
248 | // - methinks only has a past tense and is an outlier | ||
249 | // - wit has five forms, and is archaic/obscure enough that we can ignore it for now | ||
250 | std::cout << "Ignoring verb \"" << word << "\" due to non-standard number of forms." << std::endl; | ||
251 | } | ||
252 | |||
253 | verbs[word] = v; | ||
254 | |||
255 | break; | ||
256 | } | ||
257 | |||
258 | case 'A': | ||
259 | { | ||
260 | adjective adj; | ||
261 | adj.base = word; | ||
262 | if (forms.size() == 2) | ||
263 | { | ||
264 | adj.comparative = forms[0]; | ||
265 | adj.superlative = forms[1]; | ||
266 | } else { | ||
267 | // As of AGID 2014.08.11, this is only "only", which has only the form "onliest" | ||
268 | std::cout << "Ignoring adjective/adverb \"" << word << "\" due to non-standard number of forms." << std::endl; | ||
269 | } | ||
270 | |||
271 | adjectives[word] = adj; | ||
272 | |||
273 | break; | ||
274 | } | ||
275 | |||
276 | case 'N': | ||
277 | { | ||
278 | noun n; | ||
279 | n.singular = word; | ||
280 | if (forms.size() == 1) | ||
281 | { | ||
282 | n.plural = forms[0]; | ||
283 | } else { | ||
284 | // As of AGID 2014.08.11, this is non-existent. | ||
285 | std::cout << "Ignoring noun \"" << word << "\" due to non-standard number of forms." << std::endl; | ||
286 | } | ||
287 | |||
288 | nouns[word] = n; | ||
289 | |||
290 | break; | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | // Pronounciations | ||
296 | std::cout << "Reading pronunciations..." << std::endl; | ||
297 | |||
298 | std::ifstream pronfile(argv[5]); | ||
299 | if (!pronfile.is_open()) | ||
300 | { | ||
301 | std::cout << "Could not open CMUDICT file: " << argv[5] << std::endl; | ||
302 | print_usage(); | ||
303 | } | ||
304 | |||
305 | for (;;) | ||
306 | { | ||
307 | std::string line; | ||
308 | if (!getline(pronfile, line)) | ||
208 | { | 309 | { |
209 | v.past_tense = forms[0]; | 310 | break; |
210 | v.past_participle = forms[0]; | 311 | } |
211 | v.ing_form = forms[1]; | 312 | |
212 | v.s_form = forms[2]; | 313 | if (line.back() == '\r') |
213 | } else if (forms.size() == 8) | ||
214 | { | 314 | { |
215 | // As of AGID 2014.08.11, this is only "to be" | 315 | line.pop_back(); |
216 | v.past_tense = forms[0]; | ||
217 | v.past_participle = forms[2]; | ||
218 | v.ing_form = forms[3]; | ||
219 | v.s_form = forms[4]; | ||
220 | } else { | ||
221 | // Words that don't fit the cases above as of AGID 2014.08.11: | ||
222 | // - may and shall do not conjugate the way we want them to | ||
223 | // - methinks only has a past tense and is an outlier | ||
224 | // - wit has five forms, and is archaic/obscure enough that we can ignore it for now | ||
225 | std::cout << "Ignoring verb \"" << word << "\" due to non-standard number of forms." << std::endl; | ||
226 | } | 316 | } |
227 | 317 | ||
228 | verbs[word] = v; | 318 | std::regex phoneme("([A-Z][^ \\(]*)(?:\\(\\d+\\))? ([A-Z 0-9]+)"); |
319 | std::smatch phoneme_data; | ||
320 | if (std::regex_search(line, phoneme_data, phoneme)) | ||
321 | { | ||
322 | std::string canonical(phoneme_data[1]); | ||
323 | std::transform(std::begin(canonical), std::end(canonical), std::begin(canonical), ::tolower); | ||
324 | |||
325 | pronunciations[canonical].insert(phoneme_data[2]); | ||
326 | } | ||
229 | } | 327 | } |
230 | 328 | ||
231 | // Start writing output | 329 | // Start writing output |
232 | std::cout << "Writing output..." << std::endl; | 330 | std::cout << "Writing schema..." << std::endl; |
233 | 331 | ||
234 | sqlite3* ppdb; | 332 | sqlite3* ppdb; |
235 | if (sqlite3_open_v2(argv[5], &ppdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) | 333 | if (sqlite3_open_v2(argv[6], &ppdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) |
236 | { | 334 | { |
237 | std::cout << "Error opening output datafile: " << sqlite3_errmsg(ppdb) << std::endl; | 335 | std::cout << "Error opening output datafile: " << sqlite3_errmsg(ppdb) << std::endl; |
238 | print_usage(); | 336 | print_usage(); |
@@ -278,47 +376,82 @@ int main(int argc, char** argv) | |||
278 | sqlite3_stmt* schmstmt; | 376 | sqlite3_stmt* schmstmt; |
279 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &schmstmt, NULL) != SQLITE_OK) | 377 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &schmstmt, NULL) != SQLITE_OK) |
280 | { | 378 | { |
281 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 379 | db_error(ppdb, query); |
282 | sqlite3_close_v2(ppdb); | ||
283 | print_usage(); | ||
284 | } | 380 | } |
285 | 381 | ||
286 | if (sqlite3_step(schmstmt) != SQLITE_DONE) | 382 | if (sqlite3_step(schmstmt) != SQLITE_DONE) |
287 | { | 383 | { |
288 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 384 | db_error(ppdb, query); |
289 | sqlite3_close_v2(ppdb); | ||
290 | print_usage(); | ||
291 | } | 385 | } |
292 | 386 | ||
293 | sqlite3_finalize(schmstmt); | 387 | sqlite3_finalize(schmstmt); |
294 | } | 388 | } |
295 | 389 | ||
296 | std::cout << "Writing verbs..." << std::endl; | ||
297 | for (auto& mapping : verbs) | ||
298 | { | 390 | { |
299 | sqlite3_stmt* ppstmt; | 391 | progress ppgs("Writing verbs...", verbs.size()); |
300 | std::string query("INSERT INTO verbs (infinitive, past_tense, past_participle, ing_form, s_form) VALUES (?, ?, ?, ?, ?)"); | 392 | for (auto& mapping : verbs) |
301 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
302 | { | 393 | { |
303 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 394 | sqlite3_stmt* ppstmt; |
304 | sqlite3_close_v2(ppdb); | 395 | std::string query("INSERT INTO verbs (infinitive, past_tense, past_participle, ing_form, s_form) VALUES (?, ?, ?, ?, ?)"); |
305 | print_usage(); | 396 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) |
306 | } | 397 | { |
398 | db_error(ppdb, query); | ||
399 | } | ||
307 | 400 | ||
308 | sqlite3_bind_text(ppstmt, 1, mapping.second.infinitive.c_str(), mapping.second.infinitive.length(), SQLITE_STATIC); | 401 | sqlite3_bind_text(ppstmt, 1, mapping.second.infinitive.c_str(), mapping.second.infinitive.length(), SQLITE_STATIC); |
309 | sqlite3_bind_text(ppstmt, 2, mapping.second.past_tense.c_str(), mapping.second.past_tense.length(), SQLITE_STATIC); | 402 | sqlite3_bind_text(ppstmt, 2, mapping.second.past_tense.c_str(), mapping.second.past_tense.length(), SQLITE_STATIC); |
310 | sqlite3_bind_text(ppstmt, 3, mapping.second.past_participle.c_str(), mapping.second.past_participle.length(), SQLITE_STATIC); | 403 | sqlite3_bind_text(ppstmt, 3, mapping.second.past_participle.c_str(), mapping.second.past_participle.length(), SQLITE_STATIC); |
311 | sqlite3_bind_text(ppstmt, 4, mapping.second.ing_form.c_str(), mapping.second.ing_form.length(), SQLITE_STATIC); | 404 | sqlite3_bind_text(ppstmt, 4, mapping.second.ing_form.c_str(), mapping.second.ing_form.length(), SQLITE_STATIC); |
312 | sqlite3_bind_text(ppstmt, 5, mapping.second.s_form.c_str(), mapping.second.s_form.length(), SQLITE_STATIC); | 405 | sqlite3_bind_text(ppstmt, 5, mapping.second.s_form.c_str(), mapping.second.s_form.length(), SQLITE_STATIC); |
313 | 406 | ||
314 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 407 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
315 | { | 408 | { |
316 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 409 | db_error(ppdb, query); |
317 | sqlite3_close_v2(ppdb); | 410 | } |
318 | print_usage(); | ||
319 | } | ||
320 | 411 | ||
321 | sqlite3_finalize(ppstmt); | 412 | sqlite3_finalize(ppstmt); |
413 | |||
414 | std::string canonical(mapping.second.infinitive); | ||
415 | std::transform(std::begin(canonical), std::end(canonical), std::begin(canonical), ::tolower); | ||
416 | if (pronunciations.count(canonical) == 1) | ||
417 | { | ||
418 | query = "SELECT last_insert_rowid()"; | ||
419 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
420 | { | ||
421 | db_error(ppdb, query); | ||
422 | } | ||
423 | |||
424 | if (sqlite3_step(ppstmt) != SQLITE_ROW) | ||
425 | { | ||
426 | db_error(ppdb, query); | ||
427 | } | ||
428 | |||
429 | int rowid = sqlite3_column_int(ppstmt, 0); | ||
430 | |||
431 | sqlite3_finalize(ppstmt); | ||
432 | |||
433 | for (auto pronunciation : pronunciations[canonical]) | ||
434 | { | ||
435 | query = "INSERT INTO verb_pronunciations (verb_id, pronunciation) VALUES (?, ?)"; | ||
436 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
437 | { | ||
438 | db_error(ppdb, query); | ||
439 | } | ||
440 | |||
441 | sqlite3_bind_int(ppstmt, 1, rowid); | ||
442 | sqlite3_bind_text(ppstmt, 2, pronunciation.c_str(), pronunciation.length(), SQLITE_STATIC); | ||
443 | |||
444 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
445 | { | ||
446 | db_error(ppdb, query); | ||
447 | } | ||
448 | |||
449 | sqlite3_finalize(ppstmt); | ||
450 | } | ||
451 | } | ||
452 | |||
453 | ppgs.update(); | ||
454 | } | ||
322 | } | 455 | } |
323 | 456 | ||
324 | // Get nouns/adjectives/adverbs from WordNet | 457 | // Get nouns/adjectives/adverbs from WordNet |
@@ -342,110 +475,1046 @@ int main(int argc, char** argv) | |||
342 | wnpref += '/'; | 475 | wnpref += '/'; |
343 | } | 476 | } |
344 | 477 | ||
345 | std::cout << "Reading words from WordNet..." << std::endl; | 478 | // s table |
346 | std::ifstream wnsfile(wnpref + "wn_s.pl"); | ||
347 | if (!wnsfile.is_open()) | ||
348 | { | 479 | { |
349 | std::cout << "Invalid WordNet data directory." << std::endl; | 480 | std::ifstream wnsfile(wnpref + "wn_s.pl"); |
350 | print_usage(); | 481 | if (!wnsfile.is_open()) |
482 | { | ||
483 | std::cout << "Invalid WordNet data directory." << std::endl; | ||
484 | print_usage(); | ||
485 | } | ||
486 | |||
487 | std::list<std::string> lines; | ||
488 | for (;;) | ||
489 | { | ||
490 | std::string line; | ||
491 | if (!getline(wnsfile, line)) | ||
492 | { | ||
493 | break; | ||
494 | } | ||
495 | |||
496 | if (line.back() == '\r') | ||
497 | { | ||
498 | line.pop_back(); | ||
499 | } | ||
500 | |||
501 | lines.push_back(line); | ||
502 | } | ||
503 | |||
504 | progress ppgs("Writing nouns, adjectives, and adverbs...", lines.size()); | ||
505 | for (auto line : lines) | ||
506 | { | ||
507 | ppgs.update(); | ||
508 | |||
509 | std::regex relation("^s\\(([134]\\d{8}),(\\d+),'([\\w ]+)',"); | ||
510 | std::smatch relation_data; | ||
511 | if (!std::regex_search(line, relation_data, relation)) | ||
512 | { | ||
513 | continue; | ||
514 | } | ||
515 | |||
516 | int synset_id = stoi(relation_data[1]); | ||
517 | int wnum = stoi(relation_data[2]); | ||
518 | std::string word = relation_data[3]; | ||
519 | |||
520 | std::string query; | ||
521 | switch (synset_id / 100000000) | ||
522 | { | ||
523 | case 1: // Noun | ||
524 | { | ||
525 | if (nouns.count(word) == 1) | ||
526 | { | ||
527 | query = "INSERT INTO nouns (singular, plural) VALUES (?, ?)"; | ||
528 | } else { | ||
529 | query = "INSERT INTO nouns (singular) VALUES (?)"; | ||
530 | } | ||
531 | |||
532 | break; | ||
533 | } | ||
534 | |||
535 | case 2: // Verb | ||
536 | { | ||
537 | // Ignore | ||
538 | |||
539 | break; | ||
540 | } | ||
541 | |||
542 | case 3: // Adjective | ||
543 | { | ||
544 | if (adjectives.count(word) == 1) | ||
545 | { | ||
546 | query = "INSERT INTO adjectives (base_form, comparative, superlative) VALUES (?, ?, ?)"; | ||
547 | } else { | ||
548 | query = "INSERT INTO adjectives (base_form) VALUES (?)"; | ||
549 | } | ||
550 | |||
551 | break; | ||
552 | } | ||
553 | |||
554 | case 4: // Adverb | ||
555 | { | ||
556 | if (adjectives.count(word) == 1) | ||
557 | { | ||
558 | query = "INSERT INTO adverbs (base_form, comparative, superlative) VALUES (?, ?, ?)"; | ||
559 | } else { | ||
560 | query = "INSERT INTO adverbs (base_form) VALUES (?)"; | ||
561 | } | ||
562 | |||
563 | break; | ||
564 | } | ||
565 | } | ||
566 | |||
567 | sqlite3_stmt* ppstmt; | ||
568 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
569 | { | ||
570 | db_error(ppdb, query); | ||
571 | } | ||
572 | |||
573 | sqlite3_bind_text(ppstmt, 1, word.c_str(), word.length(), SQLITE_STATIC); | ||
574 | switch (synset_id / 100000000) | ||
575 | { | ||
576 | case 1: // Noun | ||
577 | { | ||
578 | if (nouns.count(word) == 1) | ||
579 | { | ||
580 | sqlite3_bind_text(ppstmt, 2, nouns[word].plural.c_str(), nouns[word].plural.length(), SQLITE_STATIC); | ||
581 | } | ||
582 | |||
583 | break; | ||
584 | } | ||
585 | |||
586 | case 3: // Adjective | ||
587 | case 4: // Adverb | ||
588 | { | ||
589 | if (adjectives.count(word) == 1) | ||
590 | { | ||
591 | sqlite3_bind_text(ppstmt, 2, adjectives[word].comparative.c_str(), adjectives[word].comparative.length(), SQLITE_STATIC); | ||
592 | sqlite3_bind_text(ppstmt, 3, adjectives[word].superlative.c_str(), adjectives[word].superlative.length(), SQLITE_STATIC); | ||
593 | } | ||
594 | |||
595 | break; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
600 | { | ||
601 | db_error(ppdb, query); | ||
602 | } | ||
603 | |||
604 | sqlite3_finalize(ppstmt); | ||
605 | |||
606 | query = "SELECT last_insert_rowid()"; | ||
607 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
608 | { | ||
609 | db_error(ppdb, query); | ||
610 | } | ||
611 | |||
612 | if (sqlite3_step(ppstmt) != SQLITE_ROW) | ||
613 | { | ||
614 | db_error(ppdb, query); | ||
615 | } | ||
616 | |||
617 | int rowid = sqlite3_column_int(ppstmt, 0); | ||
618 | wn[synset_id][wnum] = rowid; | ||
619 | |||
620 | sqlite3_finalize(ppstmt); | ||
621 | |||
622 | std::string canonical(word); | ||
623 | std::transform(std::begin(canonical), std::end(canonical), std::begin(canonical), ::tolower); | ||
624 | if (pronunciations.count(canonical) == 1) | ||
625 | { | ||
626 | for (auto pronunciation : pronunciations[canonical]) | ||
627 | { | ||
628 | switch (synset_id / 100000000) | ||
629 | { | ||
630 | case 1: // Noun | ||
631 | { | ||
632 | query = "INSERT INTO noun_pronunciations (noun_id, pronunciation) VALUES (?, ?)"; | ||
633 | |||
634 | break; | ||
635 | } | ||
636 | |||
637 | case 3: // Adjective | ||
638 | { | ||
639 | query = "INSERT INTO adjective_pronunciations (adjective_id, pronunciation) VALUES (?, ?)"; | ||
640 | |||
641 | break; | ||
642 | } | ||
643 | |||
644 | case 4: // Adverb | ||
645 | { | ||
646 | query = "INSERT INTO adverb_pronunciations (adverb_id, pronunciation) VALUES (?, ?)"; | ||
647 | |||
648 | break; | ||
649 | } | ||
650 | } | ||
651 | |||
652 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
653 | { | ||
654 | db_error(ppdb, query); | ||
655 | } | ||
656 | |||
657 | sqlite3_bind_int(ppstmt, 1, rowid); | ||
658 | sqlite3_bind_text(ppstmt, 2, pronunciation.c_str(), pronunciation.length(), SQLITE_STATIC); | ||
659 | |||
660 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
661 | { | ||
662 | db_error(ppdb, query); | ||
663 | } | ||
664 | |||
665 | sqlite3_finalize(ppstmt); | ||
666 | } | ||
667 | } | ||
668 | } | ||
351 | } | 669 | } |
352 | 670 | ||
353 | for (;;) | 671 | // While we're working on s |
354 | { | 672 | { |
355 | std::string line; | 673 | progress ppgs("Writing word synonyms...", wn.size()); |
356 | if (!getline(wnsfile, line)) | 674 | for (auto sense : wn) |
357 | { | 675 | { |
358 | break; | 676 | ppgs.update(); |
677 | |||
678 | for (auto word1 : sense.second) | ||
679 | { | ||
680 | for (auto word2 : sense.second) | ||
681 | { | ||
682 | if (word1 != word2) | ||
683 | { | ||
684 | std::string query; | ||
685 | switch (sense.first / 100000000) | ||
686 | { | ||
687 | case 1: // Noun | ||
688 | { | ||
689 | query = "INSERT INTO noun_synonymy (noun_1_id, noun_2_id) VALUES (?, ?)"; | ||
690 | |||
691 | break; | ||
692 | } | ||
693 | |||
694 | case 2: // Verb | ||
695 | { | ||
696 | // Ignore | ||
697 | |||
698 | break; | ||
699 | } | ||
700 | |||
701 | case 3: // Adjective | ||
702 | { | ||
703 | query = "INSERT INTO adjective_synonymy (adjective_1_id, adjective_2_id) VALUES (?, ?)"; | ||
704 | |||
705 | break; | ||
706 | } | ||
707 | |||
708 | case 4: // Adverb | ||
709 | { | ||
710 | query = "INSERT INTO adverb_synonymy (adverb_1_id, adverb_2_id) VALUES (?, ?)"; | ||
711 | |||
712 | break; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | sqlite3_stmt* ppstmt; | ||
717 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
718 | { | ||
719 | db_error(ppdb, query); | ||
720 | } | ||
721 | |||
722 | sqlite3_bind_int(ppstmt, 1, word1.second); | ||
723 | sqlite3_bind_int(ppstmt, 2, word2.second); | ||
724 | |||
725 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
726 | { | ||
727 | db_error(ppdb, query); | ||
728 | } | ||
729 | |||
730 | sqlite3_finalize(ppstmt); | ||
731 | } | ||
732 | } | ||
733 | } | ||
734 | } | ||
735 | } | ||
736 | |||
737 | // ant table | ||
738 | { | ||
739 | std::ifstream wnantfile(wnpref + "wn_ant.pl"); | ||
740 | if (!wnantfile.is_open()) | ||
741 | { | ||
742 | std::cout << "Invalid WordNet data directory." << std::endl; | ||
743 | print_usage(); | ||
359 | } | 744 | } |
745 | |||
746 | std::list<std::string> lines; | ||
747 | for (;;) | ||
748 | { | ||
749 | std::string line; | ||
750 | if (!getline(wnantfile, line)) | ||
751 | { | ||
752 | break; | ||
753 | } | ||
360 | 754 | ||
361 | if (line.back() == '\r') | 755 | if (line.back() == '\r') |
756 | { | ||
757 | line.pop_back(); | ||
758 | } | ||
759 | |||
760 | lines.push_back(line); | ||
761 | } | ||
762 | |||
763 | progress ppgs("Writing antonyms...", lines.size()); | ||
764 | for (auto line : lines) | ||
362 | { | 765 | { |
363 | line.pop_back(); | 766 | ppgs.update(); |
767 | |||
768 | std::regex relation("^ant\\(([134]\\d{8}),(\\d+),([134]\\d{8}),(\\d+)\\)\\."); | ||
769 | std::smatch relation_data; | ||
770 | if (!std::regex_search(line, relation_data, relation)) | ||
771 | { | ||
772 | continue; | ||
773 | } | ||
774 | |||
775 | int synset_id_1 = stoi(relation_data[1]); | ||
776 | int wnum_1 = stoi(relation_data[2]); | ||
777 | int synset_id_2 = stoi(relation_data[3]); | ||
778 | int wnum_2 = stoi(relation_data[4]); | ||
779 | |||
780 | std::string query; | ||
781 | switch (synset_id_1 / 100000000) | ||
782 | { | ||
783 | case 1: // Noun | ||
784 | { | ||
785 | query = "INSERT INTO noun_antonymy (noun_1_id, noun_2_id) VALUES (?, ?)"; | ||
786 | |||
787 | break; | ||
788 | } | ||
789 | |||
790 | case 2: // Verb | ||
791 | { | ||
792 | // Ignore | ||
793 | |||
794 | break; | ||
795 | } | ||
796 | |||
797 | case 3: // Adjective | ||
798 | { | ||
799 | query = "INSERT INTO adjective_antonymy (adjective_1_id, adjective_2_id) VALUES (?, ?)"; | ||
800 | |||
801 | break; | ||
802 | } | ||
803 | |||
804 | case 4: // Adverb | ||
805 | { | ||
806 | query = "INSERT INTO adverb_antonymy (adverb_1_id, adverb_2_id) VALUES (?, ?)"; | ||
807 | |||
808 | break; | ||
809 | } | ||
810 | } | ||
811 | |||
812 | sqlite3_stmt* ppstmt; | ||
813 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
814 | { | ||
815 | db_error(ppdb, query); | ||
816 | } | ||
817 | |||
818 | sqlite3_bind_int(ppstmt, 1, wn[synset_id_1][wnum_1]); | ||
819 | sqlite3_bind_int(ppstmt, 2, wn[synset_id_2][wnum_2]); | ||
820 | |||
821 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
822 | { | ||
823 | db_error(ppdb, query); | ||
824 | } | ||
825 | |||
826 | sqlite3_finalize(ppstmt); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | // at table | ||
831 | { | ||
832 | std::ifstream wnatfile(wnpref + "wn_at.pl"); | ||
833 | if (!wnatfile.is_open()) | ||
834 | { | ||
835 | std::cout << "Invalid WordNet data directory." << std::endl; | ||
836 | print_usage(); | ||
364 | } | 837 | } |
838 | |||
839 | std::list<std::string> lines; | ||
840 | for (;;) | ||
841 | { | ||
842 | std::string line; | ||
843 | if (!getline(wnatfile, line)) | ||
844 | { | ||
845 | break; | ||
846 | } | ||
365 | 847 | ||
366 | std::regex relation("^s\\(([134]\\d{8}),(\\d+),'([\\w ]+)',"); | 848 | if (line.back() == '\r') |
367 | std::smatch relation_data; | 849 | { |
368 | if (!std::regex_search(line, relation_data, relation)) | 850 | line.pop_back(); |
851 | } | ||
852 | |||
853 | lines.push_back(line); | ||
854 | } | ||
855 | |||
856 | progress ppgs("Writing variations...", lines.size()); | ||
857 | for (auto line : lines) | ||
369 | { | 858 | { |
370 | continue; | 859 | ppgs.update(); |
860 | |||
861 | std::regex relation("^at\\((1\\d{8}),(3\\d{8})\\)\\."); | ||
862 | std::smatch relation_data; | ||
863 | if (!std::regex_search(line, relation_data, relation)) | ||
864 | { | ||
865 | continue; | ||
866 | } | ||
867 | |||
868 | int synset_id_1 = stoi(relation_data[1]); | ||
869 | int synset_id_2 = stoi(relation_data[2]); | ||
870 | std::string query("INSERT INTO variation (noun_id, adjective_id) VALUES (?, ?)"); | ||
871 | |||
872 | for (auto mapping1 : wn[synset_id_1]) | ||
873 | { | ||
874 | for (auto mapping2 : wn[synset_id_2]) | ||
875 | { | ||
876 | sqlite3_stmt* ppstmt; | ||
877 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.size(), &ppstmt, NULL) != SQLITE_OK) | ||
878 | { | ||
879 | db_error(ppdb, query); | ||
880 | } | ||
881 | |||
882 | sqlite3_bind_int(ppstmt, 1, mapping1.second); | ||
883 | sqlite3_bind_int(ppstmt, 2, mapping2.second); | ||
884 | |||
885 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
886 | { | ||
887 | db_error(ppdb, query); | ||
888 | } | ||
889 | |||
890 | sqlite3_finalize(ppstmt); | ||
891 | } | ||
892 | } | ||
371 | } | 893 | } |
894 | } | ||
895 | |||
896 | // hyp table | ||
897 | { | ||
898 | std::ifstream wnhypfile(wnpref + "wn_hyp.pl"); | ||
899 | if (!wnhypfile.is_open()) | ||
900 | { | ||
901 | std::cout << "Invalid WordNet data directory." << std::endl; | ||
902 | print_usage(); | ||
903 | } | ||
904 | |||
905 | std::list<std::string> lines; | ||
906 | for (;;) | ||
907 | { | ||
908 | std::string line; | ||
909 | if (!getline(wnhypfile, line)) | ||
910 | { | ||
911 | break; | ||
912 | } | ||
372 | 913 | ||
373 | int synset_id = stoi(relation_data[1]); | 914 | if (line.back() == '\r') |
374 | int wnum = stoi(relation_data[2]); | 915 | { |
375 | std::string word = relation_data[3]; | 916 | line.pop_back(); |
917 | } | ||
918 | |||
919 | lines.push_back(line); | ||
920 | } | ||
376 | 921 | ||
377 | std::string query; | 922 | progress ppgs("Writing hypernyms...", lines.size()); |
378 | switch (synset_id / 100000000) | 923 | for (auto line : lines) |
379 | { | 924 | { |
380 | case 1: // Noun | 925 | ppgs.update(); |
926 | |||
927 | std::regex relation("^hyp\\((1\\d{8}),(1\\d{8})\\)\\."); | ||
928 | std::smatch relation_data; | ||
929 | if (!std::regex_search(line, relation_data, relation)) | ||
930 | { | ||
931 | continue; | ||
932 | } | ||
933 | |||
934 | int synset_id_1 = stoi(relation_data[1]); | ||
935 | int synset_id_2 = stoi(relation_data[2]); | ||
936 | std::string query("INSERT INTO hypernymy (hyponym_id, hypernym_id) VALUES (?, ?)"); | ||
937 | |||
938 | for (auto mapping1 : wn[synset_id_1]) | ||
939 | { | ||
940 | for (auto mapping2 : wn[synset_id_2]) | ||
941 | { | ||
942 | sqlite3_stmt* ppstmt; | ||
943 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.size(), &ppstmt, NULL) != SQLITE_OK) | ||
944 | { | ||
945 | db_error(ppdb, query); | ||
946 | } | ||
947 | |||
948 | sqlite3_bind_int(ppstmt, 1, mapping1.second); | ||
949 | sqlite3_bind_int(ppstmt, 2, mapping2.second); | ||
950 | |||
951 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
952 | { | ||
953 | db_error(ppdb, query); | ||
954 | } | ||
955 | |||
956 | sqlite3_finalize(ppstmt); | ||
957 | } | ||
958 | } | ||
959 | } | ||
960 | } | ||
961 | |||
962 | // ins table | ||
963 | { | ||
964 | std::ifstream wninsfile(wnpref + "wn_ins.pl"); | ||
965 | if (!wninsfile.is_open()) | ||
966 | { | ||
967 | std::cout << "Invalid WordNet data directory." << std::endl; | ||
968 | print_usage(); | ||
969 | } | ||
970 | |||
971 | std::list<std::string> lines; | ||
972 | for (;;) | ||
973 | { | ||
974 | std::string line; | ||
975 | if (!getline(wninsfile, line)) | ||
381 | { | 976 | { |
382 | query = "INSERT INTO nouns (form) VALUES (?)"; | ||
383 | |||
384 | break; | 977 | break; |
385 | } | 978 | } |
979 | |||
980 | if (line.back() == '\r') | ||
981 | { | ||
982 | line.pop_back(); | ||
983 | } | ||
386 | 984 | ||
387 | case 2: // Verb | 985 | lines.push_back(line); |
986 | } | ||
987 | |||
988 | progress ppgs("Writing instantiations...", lines.size()); | ||
989 | for (auto line : lines) | ||
990 | { | ||
991 | ppgs.update(); | ||
992 | |||
993 | std::regex relation("^ins\\((1\\d{8}),(1\\d{8})\\)\\."); | ||
994 | std::smatch relation_data; | ||
995 | if (!std::regex_search(line, relation_data, relation)) | ||
996 | { | ||
997 | continue; | ||
998 | } | ||
999 | |||
1000 | int synset_id_1 = stoi(relation_data[1]); | ||
1001 | int synset_id_2 = stoi(relation_data[2]); | ||
1002 | std::string query("INSERT INTO instantiation (instance_id, class_id) VALUES (?, ?)"); | ||
1003 | |||
1004 | for (auto mapping1 : wn[synset_id_1]) | ||
1005 | { | ||
1006 | for (auto mapping2 : wn[synset_id_2]) | ||
1007 | { | ||
1008 | sqlite3_stmt* ppstmt; | ||
1009 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.size(), &ppstmt, NULL) != SQLITE_OK) | ||
1010 | { | ||
1011 | db_error(ppdb, query); | ||
1012 | } | ||
1013 | |||
1014 | sqlite3_bind_int(ppstmt, 1, mapping1.second); | ||
1015 | sqlite3_bind_int(ppstmt, 2, mapping2.second); | ||
1016 | |||
1017 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
1018 | { | ||
1019 | db_error(ppdb, query); | ||
1020 | } | ||
1021 | |||
1022 | sqlite3_finalize(ppstmt); | ||
1023 | } | ||
1024 | } | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | // mm table | ||
1029 | { | ||
1030 | std::ifstream wnmmfile(wnpref + "wn_mm.pl"); | ||
1031 | if (!wnmmfile.is_open()) | ||
1032 | { | ||
1033 | std::cout << "Invalid WordNet data directory." << std::endl; | ||
1034 | print_usage(); | ||
1035 | } | ||
1036 | |||
1037 | std::list<std::string> lines; | ||
1038 | for (;;) | ||
1039 | { | ||
1040 | std::string line; | ||
1041 | if (!getline(wnmmfile, line)) | ||
388 | { | 1042 | { |
389 | // Ignore | ||
390 | |||
391 | break; | 1043 | break; |
392 | } | 1044 | } |
1045 | |||
1046 | if (line.back() == '\r') | ||
1047 | { | ||
1048 | line.pop_back(); | ||
1049 | } | ||
1050 | |||
1051 | lines.push_back(line); | ||
1052 | } | ||
1053 | |||
1054 | progress ppgs("Writing member meronyms...", lines.size()); | ||
1055 | for (auto line : lines) | ||
1056 | { | ||
1057 | ppgs.update(); | ||
393 | 1058 | ||
394 | case 3: // Adjective | 1059 | std::regex relation("^mm\\((1\\d{8}),(1\\d{8})\\)\\."); |
1060 | std::smatch relation_data; | ||
1061 | if (!std::regex_search(line, relation_data, relation)) | ||
1062 | { | ||
1063 | continue; | ||
1064 | } | ||
1065 | |||
1066 | int synset_id_1 = stoi(relation_data[1]); | ||
1067 | int synset_id_2 = stoi(relation_data[2]); | ||
1068 | std::string query("INSERT INTO member_meronymy (holonym_id, meronym_id) VALUES (?, ?)"); | ||
1069 | |||
1070 | for (auto mapping1 : wn[synset_id_1]) | ||
1071 | { | ||
1072 | for (auto mapping2 : wn[synset_id_2]) | ||
1073 | { | ||
1074 | sqlite3_stmt* ppstmt; | ||
1075 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.size(), &ppstmt, NULL) != SQLITE_OK) | ||
1076 | { | ||
1077 | db_error(ppdb, query); | ||
1078 | } | ||
1079 | |||
1080 | sqlite3_bind_int(ppstmt, 1, mapping1.second); | ||
1081 | sqlite3_bind_int(ppstmt, 2, mapping2.second); | ||
1082 | |||
1083 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
1084 | { | ||
1085 | db_error(ppdb, query); | ||
1086 | } | ||
1087 | |||
1088 | sqlite3_finalize(ppstmt); | ||
1089 | } | ||
1090 | } | ||
1091 | } | ||
1092 | } | ||
1093 | |||
1094 | // ms table | ||
1095 | { | ||
1096 | std::ifstream wnmsfile(wnpref + "wn_ms.pl"); | ||
1097 | if (!wnmsfile.is_open()) | ||
1098 | { | ||
1099 | std::cout << "Invalid WordNet data directory." << std::endl; | ||
1100 | print_usage(); | ||
1101 | } | ||
1102 | |||
1103 | std::list<std::string> lines; | ||
1104 | for (;;) | ||
1105 | { | ||
1106 | std::string line; | ||
1107 | if (!getline(wnmsfile, line)) | ||
395 | { | 1108 | { |
396 | query = "INSERT INTO adjectives (form) VALUES (?)"; | ||
397 | |||
398 | break; | 1109 | break; |
399 | } | 1110 | } |
1111 | |||
1112 | if (line.back() == '\r') | ||
1113 | { | ||
1114 | line.pop_back(); | ||
1115 | } | ||
400 | 1116 | ||
401 | case 4: // Adverb | 1117 | lines.push_back(line); |
1118 | } | ||
1119 | |||
1120 | progress ppgs("Writing substance meronyms...", lines.size()); | ||
1121 | for (auto line : lines) | ||
1122 | { | ||
1123 | ppgs.update(); | ||
1124 | |||
1125 | std::regex relation("^ms\\((1\\d{8}),(1\\d{8})\\)\\."); | ||
1126 | std::smatch relation_data; | ||
1127 | if (!std::regex_search(line, relation_data, relation)) | ||
1128 | { | ||
1129 | continue; | ||
1130 | } | ||
1131 | |||
1132 | int synset_id_1 = stoi(relation_data[1]); | ||
1133 | int synset_id_2 = stoi(relation_data[2]); | ||
1134 | std::string query("INSERT INTO substance_meronymy (holonym_id, meronym_id) VALUES (?, ?)"); | ||
1135 | |||
1136 | for (auto mapping1 : wn[synset_id_1]) | ||
1137 | { | ||
1138 | for (auto mapping2 : wn[synset_id_2]) | ||
1139 | { | ||
1140 | sqlite3_stmt* ppstmt; | ||
1141 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.size(), &ppstmt, NULL) != SQLITE_OK) | ||
1142 | { | ||
1143 | db_error(ppdb, query); | ||
1144 | } | ||
1145 | |||
1146 | sqlite3_bind_int(ppstmt, 1, mapping1.second); | ||
1147 | sqlite3_bind_int(ppstmt, 2, mapping2.second); | ||
1148 | |||
1149 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
1150 | { | ||
1151 | db_error(ppdb, query); | ||
1152 | } | ||
1153 | |||
1154 | sqlite3_finalize(ppstmt); | ||
1155 | } | ||
1156 | } | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1160 | // mm table | ||
1161 | { | ||
1162 | std::ifstream wnmpfile(wnpref + "wn_mp.pl"); | ||
1163 | if (!wnmpfile.is_open()) | ||
1164 | { | ||
1165 | std::cout << "Invalid WordNet data directory." << std::endl; | ||
1166 | print_usage(); | ||
1167 | } | ||
1168 | |||
1169 | std::list<std::string> lines; | ||
1170 | for (;;) | ||
1171 | { | ||
1172 | std::string line; | ||
1173 | if (!getline(wnmpfile, line)) | ||
402 | { | 1174 | { |
403 | query = "INSERT INTO adverbs (form) VALUES (?)"; | ||
404 | |||
405 | break; | 1175 | break; |
406 | } | 1176 | } |
1177 | |||
1178 | if (line.back() == '\r') | ||
1179 | { | ||
1180 | line.pop_back(); | ||
1181 | } | ||
1182 | |||
1183 | lines.push_back(line); | ||
407 | } | 1184 | } |
408 | 1185 | ||
409 | sqlite3_stmt* ppstmt; | 1186 | progress ppgs("Writing part meronyms...", lines.size()); |
410 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | 1187 | for (auto line : lines) |
1188 | { | ||
1189 | ppgs.update(); | ||
1190 | |||
1191 | std::regex relation("^mp\\((1\\d{8}),(1\\d{8})\\)\\."); | ||
1192 | std::smatch relation_data; | ||
1193 | if (!std::regex_search(line, relation_data, relation)) | ||
1194 | { | ||
1195 | continue; | ||
1196 | } | ||
1197 | |||
1198 | int synset_id_1 = stoi(relation_data[1]); | ||
1199 | int synset_id_2 = stoi(relation_data[2]); | ||
1200 | std::string query("INSERT INTO part_meronymy (holonym_id, meronym_id) VALUES (?, ?)"); | ||
1201 | |||
1202 | for (auto mapping1 : wn[synset_id_1]) | ||
1203 | { | ||
1204 | for (auto mapping2 : wn[synset_id_2]) | ||
1205 | { | ||
1206 | sqlite3_stmt* ppstmt; | ||
1207 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.size(), &ppstmt, NULL) != SQLITE_OK) | ||
1208 | { | ||
1209 | db_error(ppdb, query); | ||
1210 | } | ||
1211 | |||
1212 | sqlite3_bind_int(ppstmt, 1, mapping1.second); | ||
1213 | sqlite3_bind_int(ppstmt, 2, mapping2.second); | ||
1214 | |||
1215 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
1216 | { | ||
1217 | db_error(ppdb, query); | ||
1218 | } | ||
1219 | |||
1220 | sqlite3_finalize(ppstmt); | ||
1221 | } | ||
1222 | } | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | // per table | ||
1227 | { | ||
1228 | std::ifstream wnperfile(wnpref + "wn_per.pl"); | ||
1229 | if (!wnperfile.is_open()) | ||
411 | { | 1230 | { |
412 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 1231 | std::cout << "Invalid WordNet data directory." << std::endl; |
413 | sqlite3_close_v2(ppdb); | ||
414 | print_usage(); | 1232 | print_usage(); |
415 | } | 1233 | } |
1234 | |||
1235 | std::list<std::string> lines; | ||
1236 | for (;;) | ||
1237 | { | ||
1238 | std::string line; | ||
1239 | if (!getline(wnperfile, line)) | ||
1240 | { | ||
1241 | break; | ||
1242 | } | ||
1243 | |||
1244 | if (line.back() == '\r') | ||
1245 | { | ||
1246 | line.pop_back(); | ||
1247 | } | ||
1248 | |||
1249 | lines.push_back(line); | ||
1250 | } | ||
1251 | |||
1252 | progress ppgs("Writing pertainyms and mannernyms...", lines.size()); | ||
1253 | for (auto line : lines) | ||
1254 | { | ||
1255 | ppgs.update(); | ||
1256 | |||
1257 | std::regex relation("^per\\(([34]\\d{8}),(\\d+),([13]\\d{8}),(\\d+)\\)\\."); | ||
1258 | std::smatch relation_data; | ||
1259 | if (!std::regex_search(line, relation_data, relation)) | ||
1260 | { | ||
1261 | continue; | ||
1262 | } | ||
1263 | |||
1264 | int synset_id_1 = stoi(relation_data[1]); | ||
1265 | int wnum_1 = stoi(relation_data[2]); | ||
1266 | int synset_id_2 = stoi(relation_data[3]); | ||
1267 | int wnum_2 = stoi(relation_data[4]); | ||
1268 | std::string query; | ||
1269 | switch (synset_id_1 / 100000000) | ||
1270 | { | ||
1271 | case 3: // Adjective | ||
1272 | { | ||
1273 | // This is a pertainym, the second word should be a noun | ||
1274 | // Technically it can be an adjective but we're ignoring that | ||
1275 | if (synset_id_2 / 100000000 != 1) | ||
1276 | { | ||
1277 | continue; | ||
1278 | } | ||
1279 | |||
1280 | query = "INSERT INTO pertainymy (pertainym_id, noun_id) VALUES (?, ?)"; | ||
1281 | |||
1282 | break; | ||
1283 | } | ||
1284 | |||
1285 | case 4: // Adverb | ||
1286 | { | ||
1287 | // This is a mannernym, the second word should be an adjective | ||
1288 | if (synset_id_2 / 100000000 != 3) | ||
1289 | { | ||
1290 | continue; | ||
1291 | } | ||
1292 | |||
1293 | query = "INSERT INTO mannernymy (mannernym_id, adjective_id) VALUES (?, ?)"; | ||
1294 | |||
1295 | break; | ||
1296 | } | ||
1297 | } | ||
1298 | |||
1299 | sqlite3_stmt* ppstmt; | ||
1300 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
1301 | { | ||
1302 | db_error(ppdb, query); | ||
1303 | } | ||
416 | 1304 | ||
417 | sqlite3_bind_text(ppstmt, 1, word.c_str(), word.length(), SQLITE_STATIC); | 1305 | sqlite3_bind_int(ppstmt, 1, wn[synset_id_1][wnum_1]); |
1306 | sqlite3_bind_int(ppstmt, 2, wn[synset_id_2][wnum_2]); | ||
418 | 1307 | ||
419 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | 1308 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
1309 | { | ||
1310 | db_error(ppdb, query); | ||
1311 | } | ||
1312 | |||
1313 | sqlite3_finalize(ppstmt); | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1317 | // sa table | ||
1318 | { | ||
1319 | std::ifstream wnsafile(wnpref + "wn_sa.pl"); | ||
1320 | if (!wnsafile.is_open()) | ||
420 | { | 1321 | { |
421 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 1322 | std::cout << "Invalid WordNet data directory." << std::endl; |
422 | sqlite3_close_v2(ppdb); | ||
423 | print_usage(); | 1323 | print_usage(); |
424 | } | 1324 | } |
1325 | |||
1326 | std::list<std::string> lines; | ||
1327 | for (;;) | ||
1328 | { | ||
1329 | std::string line; | ||
1330 | if (!getline(wnsafile, line)) | ||
1331 | { | ||
1332 | break; | ||
1333 | } | ||
1334 | |||
1335 | if (line.back() == '\r') | ||
1336 | { | ||
1337 | line.pop_back(); | ||
1338 | } | ||
1339 | |||
1340 | lines.push_back(line); | ||
1341 | } | ||
425 | 1342 | ||
426 | sqlite3_finalize(ppstmt); | 1343 | progress ppgs("Writing specifications...", lines.size()); |
1344 | for (auto line : lines) | ||
1345 | { | ||
1346 | ppgs.update(); | ||
1347 | |||
1348 | std::regex relation("^per\\((3\\d{8}),(\\d+),(3\\d{8}),(\\d+)\\)\\."); | ||
1349 | std::smatch relation_data; | ||
1350 | if (!std::regex_search(line, relation_data, relation)) | ||
1351 | { | ||
1352 | continue; | ||
1353 | } | ||
1354 | |||
1355 | int synset_id_1 = stoi(relation_data[1]); | ||
1356 | int wnum_1 = stoi(relation_data[2]); | ||
1357 | int synset_id_2 = stoi(relation_data[3]); | ||
1358 | int wnum_2 = stoi(relation_data[4]); | ||
1359 | std::string query("INSERT INTO specification (general_id, specific_id) VALUES (?, ?)"); | ||
1360 | |||
1361 | sqlite3_stmt* ppstmt; | ||
1362 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
1363 | { | ||
1364 | db_error(ppdb, query); | ||
1365 | } | ||
1366 | |||
1367 | sqlite3_bind_int(ppstmt, 1, wn[synset_id_1][wnum_1]); | ||
1368 | sqlite3_bind_int(ppstmt, 2, wn[synset_id_2][wnum_2]); | ||
427 | 1369 | ||
428 | query = "SELECT last_insert_rowid()"; | 1370 | if (sqlite3_step(ppstmt) != SQLITE_DONE) |
429 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | 1371 | { |
1372 | db_error(ppdb, query); | ||
1373 | } | ||
1374 | |||
1375 | sqlite3_finalize(ppstmt); | ||
1376 | } | ||
1377 | } | ||
1378 | /* | ||
1379 | // sim table | ||
1380 | { | ||
1381 | std::ifstream wnsimfile(wnpref + "wn_sim.pl"); | ||
1382 | if (!wnsimfile.is_open()) | ||
430 | { | 1383 | { |
431 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 1384 | std::cout << "Invalid WordNet data directory." << std::endl; |
432 | sqlite3_close_v2(ppdb); | ||
433 | print_usage(); | 1385 | print_usage(); |
434 | } | 1386 | } |
1387 | |||
1388 | std::list<std::string> lines; | ||
1389 | for (;;) | ||
1390 | { | ||
1391 | std::string line; | ||
1392 | if (!getline(wnsimfile, line)) | ||
1393 | { | ||
1394 | break; | ||
1395 | } | ||
1396 | |||
1397 | if (line.back() == '\r') | ||
1398 | { | ||
1399 | line.pop_back(); | ||
1400 | } | ||
1401 | |||
1402 | lines.push_back(line); | ||
1403 | } | ||
435 | 1404 | ||
436 | if (sqlite3_step(ppstmt) != SQLITE_ROW) | 1405 | progress ppgs("Writing sense synonyms...", lines.size()); |
1406 | for (auto line : lines) | ||
1407 | { | ||
1408 | ppgs.update(); | ||
1409 | |||
1410 | std::regex relation("^sim\\((3\\d{8}),(3\\d{8})\\)\\."); | ||
1411 | std::smatch relation_data; | ||
1412 | if (!std::regex_search(line, relation_data, relation)) | ||
1413 | { | ||
1414 | continue; | ||
1415 | } | ||
1416 | |||
1417 | int synset_id_1 = stoi(relation_data[1]); | ||
1418 | int synset_id_2 = stoi(relation_data[2]); | ||
1419 | std::string query("INSERT INTO adjective_synonymy (adjective_1_id, adjective_2_id) VALUES (?, ?)"); | ||
1420 | |||
1421 | for (auto mapping1 : wn[synset_id_1]) | ||
1422 | { | ||
1423 | for (auto mapping2 : wn[synset_id_2]) | ||
1424 | { | ||
1425 | sqlite3_stmt* ppstmt; | ||
1426 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.size(), &ppstmt, NULL) != SQLITE_OK) | ||
1427 | { | ||
1428 | db_error(ppdb, query); | ||
1429 | } | ||
1430 | |||
1431 | sqlite3_bind_int(ppstmt, 1, mapping1.second); | ||
1432 | sqlite3_bind_int(ppstmt, 2, mapping2.second); | ||
1433 | |||
1434 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
1435 | { | ||
1436 | db_error(ppdb, query); | ||
1437 | } | ||
1438 | |||
1439 | sqlite3_reset(ppstmt); | ||
1440 | sqlite3_clear_bindings(ppstmt); | ||
1441 | |||
1442 | sqlite3_bind_int(ppstmt, 1, mapping2.second); | ||
1443 | sqlite3_bind_int(ppstmt, 2, mapping1.second); | ||
1444 | |||
1445 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
1446 | { | ||
1447 | db_error(ppdb, query); | ||
1448 | } | ||
1449 | |||
1450 | sqlite3_finalize(ppstmt); | ||
1451 | } | ||
1452 | } | ||
1453 | } | ||
1454 | } | ||
1455 | */ | ||
1456 | // syntax table | ||
1457 | { | ||
1458 | std::ifstream wnsyntaxfile(wnpref + "wn_syntax.pl"); | ||
1459 | if (!wnsyntaxfile.is_open()) | ||
437 | { | 1460 | { |
438 | std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl; | 1461 | std::cout << "Invalid WordNet data directory." << std::endl; |
439 | sqlite3_close_v2(ppdb); | ||
440 | print_usage(); | 1462 | print_usage(); |
441 | } | 1463 | } |
1464 | |||
1465 | std::list<std::string> lines; | ||
1466 | for (;;) | ||
1467 | { | ||
1468 | std::string line; | ||
1469 | if (!getline(wnsyntaxfile, line)) | ||
1470 | { | ||
1471 | break; | ||
1472 | } | ||
442 | 1473 | ||
443 | wn[synset_id][wnum] = sqlite3_column_int(ppstmt, 0); | 1474 | if (line.back() == '\r') |
1475 | { | ||
1476 | line.pop_back(); | ||
1477 | } | ||
1478 | |||
1479 | lines.push_back(line); | ||
1480 | } | ||
444 | 1481 | ||
445 | sqlite3_finalize(ppstmt); | 1482 | progress ppgs("Writing adjective syntax markers...", lines.size()); |
1483 | for (auto line : lines) | ||
1484 | { | ||
1485 | ppgs.update(); | ||
1486 | |||
1487 | std::regex relation("^syntax\\((3\\d{8}),(\\d+),([ipa])p?\\)\\."); | ||
1488 | std::smatch relation_data; | ||
1489 | if (!std::regex_search(line, relation_data, relation)) | ||
1490 | { | ||
1491 | continue; | ||
1492 | } | ||
1493 | |||
1494 | int synset_id = stoi(relation_data[1]); | ||
1495 | int wnum = stoi(relation_data[2]); | ||
1496 | std::string syn = relation_data[3]; | ||
1497 | std::string query("UPDATE adjectives SET position = ? WHERE adjective_id = ?"); | ||
1498 | |||
1499 | sqlite3_stmt* ppstmt; | ||
1500 | if (sqlite3_prepare_v2(ppdb, query.c_str(), query.size(), &ppstmt, NULL) != SQLITE_OK) | ||
1501 | { | ||
1502 | db_error(ppdb, query); | ||
1503 | } | ||
1504 | |||
1505 | sqlite3_bind_text(ppstmt, 1, syn.c_str(), 1, SQLITE_STATIC); | ||
1506 | sqlite3_bind_int(ppstmt, 2, wn[synset_id][wnum]); | ||
1507 | |||
1508 | if (sqlite3_step(ppstmt) != SQLITE_DONE) | ||
1509 | { | ||
1510 | db_error(ppdb, query); | ||
1511 | } | ||
1512 | |||
1513 | sqlite3_finalize(ppstmt); | ||
1514 | } | ||
446 | } | 1515 | } |
447 | 1516 | ||
448 | sqlite3_close_v2(ppdb); | 1517 | sqlite3_close_v2(ppdb); |
449 | 1518 | ||
450 | std::cout << "Done." << std::endl; | 1519 | std::cout << "Done." << std::endl; |
451 | } \ No newline at end of file | 1520 | } |
diff --git a/progress.h b/progress.h new file mode 100644 index 0000000..81f07a3 --- /dev/null +++ b/progress.h | |||
@@ -0,0 +1,50 @@ | |||
1 | #ifndef PROGRESS_H_A34EF856 | ||
2 | #define PROGRESS_H_A34EF856 | ||
3 | |||
4 | #include <string> | ||
5 | |||
6 | class progress { | ||
7 | private: | ||
8 | std::string message; | ||
9 | int total; | ||
10 | int cur = 0; | ||
11 | int lprint = 0; | ||
12 | |||
13 | public: | ||
14 | progress(std::string message, int total) : message(message), total(total) | ||
15 | { | ||
16 | std::cout << message << " 0%" << std::flush; | ||
17 | } | ||
18 | |||
19 | void update(int val) | ||
20 | { | ||
21 | if (val <= total) | ||
22 | { | ||
23 | cur = val; | ||
24 | } else { | ||
25 | cur = total; | ||
26 | } | ||
27 | |||
28 | int pp = cur * 100 / total; | ||
29 | if (pp != lprint) | ||
30 | { | ||
31 | lprint = pp; | ||
32 | |||
33 | std::cout << "\b\b\b\b" << std::right; | ||
34 | std::cout.width(3); | ||
35 | std::cout << pp << "%" << std::flush; | ||
36 | } | ||
37 | } | ||
38 | |||
39 | void update() | ||
40 | { | ||
41 | update(cur+1); | ||
42 | } | ||
43 | |||
44 | ~progress() | ||
45 | { | ||
46 | std::cout << "\b\b\b\b100%" << std::endl; | ||
47 | } | ||
48 | }; | ||
49 | |||
50 | #endif /* end of include guard: PROGRESS_H_A34EF856 */ | ||
diff --git a/schema.sql b/schema.sql index 62dd780..fd55734 100644 --- a/schema.sql +++ b/schema.sql | |||
@@ -34,20 +34,25 @@ CREATE TABLE `verb_groups` ( | |||
34 | DROP TABLE IF EXISTS `adjectives`; | 34 | DROP TABLE IF EXISTS `adjectives`; |
35 | CREATE TABLE `adjectives` ( | 35 | CREATE TABLE `adjectives` ( |
36 | `adjective_id` INTEGER PRIMARY KEY, | 36 | `adjective_id` INTEGER PRIMARY KEY, |
37 | `form` VARCHAR(32) NOT NULL, | 37 | `base_form` VARCHAR(32) NOT NULL, |
38 | `comparative` VARCHAR(32), | ||
39 | `superlative` VARCHAR(32), | ||
38 | `position` CHAR(1) | 40 | `position` CHAR(1) |
39 | ); | 41 | ); |
40 | 42 | ||
41 | DROP TABLE IF EXISTS `adverbs`; | 43 | DROP TABLE IF EXISTS `adverbs`; |
42 | CREATE TABLE `adverbs` ( | 44 | CREATE TABLE `adverbs` ( |
43 | `adverb_id` INTEGER PRIMARY KEY, | 45 | `adverb_id` INTEGER PRIMARY KEY, |
44 | `form` VARCHAR(32) NOT NULL | 46 | `base_form` VARCHAR(32) NOT NULL, |
47 | `comparative` VARCHAR(32), | ||
48 | `superlative` VARCHAR(32) | ||
45 | ); | 49 | ); |
46 | 50 | ||
47 | DROP TABLE IF EXISTS `nouns`; | 51 | DROP TABLE IF EXISTS `nouns`; |
48 | CREATE TABLE `nouns` ( | 52 | CREATE TABLE `nouns` ( |
49 | `noun_id` INTEGER PRIMARY KEY, | 53 | `noun_id` INTEGER PRIMARY KEY, |
50 | `form` VARCHAR(32) NOT NULL | 54 | `singular` VARCHAR(32) NOT NULL, |
55 | `plural` VARCHAR(32) | ||
51 | ); | 56 | ); |
52 | 57 | ||
53 | DROP TABLE IF EXISTS `hypernymy`; | 58 | DROP TABLE IF EXISTS `hypernymy`; |
@@ -146,10 +151,54 @@ CREATE TABLE `mannernymy` ( | |||
146 | FOREIGN KEY (`mannernym_id`) REFERENCES `adverbs`(`adverb_id`) | 151 | FOREIGN KEY (`mannernym_id`) REFERENCES `adverbs`(`adverb_id`) |
147 | ); | 152 | ); |
148 | 153 | ||
149 | DROP TABLE IF EXISTS `synonymy`; | 154 | DROP TABLE IF EXISTS `noun_synonymy`; |
150 | CREATE TABLE `synonymy` ( | 155 | CREATE TABLE `noun_synonymy` ( |
156 | `noun_1_id` INTEGER NOT NULL, | ||
157 | `noun_2_id` INTEGER NOT NULL, | ||
158 | FOREIGN KEY (`noun_1_id`) REFERENCES `nouns`(`nouns_id`), | ||
159 | FOREIGN KEY (`noun_2_id`) REFERENCES `nouns`(`nouns_id`) | ||
160 | ); | ||
161 | |||
162 | DROP TABLE IF EXISTS `adjective_synonymy`; | ||
163 | CREATE TABLE `adjective_synonymy` ( | ||
151 | `adjective_1_id` INTEGER NOT NULL, | 164 | `adjective_1_id` INTEGER NOT NULL, |
152 | `adjective_2_id` INTEGER NOT NULL, | 165 | `adjective_2_id` INTEGER NOT NULL, |
153 | FOREIGN KEY (`adjective_1_id`) REFERENCES `adjectives`(`adjective_id`), | 166 | FOREIGN KEY (`adjective_1_id`) REFERENCES `adjectives`(`adjective_id`), |
154 | FOREIGN KEY (`adjective_2_id`) REFERENCES `adjectives`(`adjective_id`) | 167 | FOREIGN KEY (`adjective_2_id`) REFERENCES `adjectives`(`adjective_id`) |
155 | ); | 168 | ); |
169 | |||
170 | DROP TABLE IF EXISTS `adverb_synonymy`; | ||
171 | CREATE TABLE `adverb_synonymy` ( | ||
172 | `adverb_1_id` INTEGER NOT NULL, | ||
173 | `adverb_2_id` INTEGER NOT NULL, | ||
174 | FOREIGN KEY (`adverb_1_id`) REFERENCES `adverbs`(`adverb_id`), | ||
175 | FOREIGN KEY (`adverb_2_id`) REFERENCES `adverbs`(`adverb_id`) | ||
176 | ); | ||
177 | |||
178 | DROP TABLE IF EXISTS `noun_pronunciations`; | ||
179 | CREATE TABLE `noun_pronunciations` ( | ||
180 | `noun_id` INTEGER NOT NULL, | ||
181 | `pronunciation` VARCHAR(64) NOT NULL, | ||
182 | FOREIGN KEY (`noun_id`) REFERENCES `nouns`(`noun_id`) | ||
183 | ); | ||
184 | |||
185 | DROP TABLE IF EXISTS `verb_pronunciations`; | ||
186 | CREATE TABLE `verb_pronunciations` ( | ||
187 | `verb_id` INTEGER NOT NULL, | ||
188 | `pronunciation` VARCHAR(64) NOT NULL, | ||
189 | FOREIGN KEY (`verb_id`) REFERENCES `verbs`(`verb_id`) | ||
190 | ); | ||
191 | |||
192 | DROP TABLE IF EXISTS `adjective_pronunciations`; | ||
193 | CREATE TABLE `adjective_pronunciations` ( | ||
194 | `adjective_id` INTEGER NOT NULL, | ||
195 | `pronunciation` VARCHAR(64) NOT NULL, | ||
196 | FOREIGN KEY (`adjective_id`) REFERENCES `adjectives`(`adjective_id`) | ||
197 | ); | ||
198 | |||
199 | DROP TABLE IF EXISTS `adverb_pronunciations`; | ||
200 | CREATE TABLE `adverb_pronunciations` ( | ||
201 | `adverb_id` INTEGER NOT NULL, | ||
202 | `pronunciation` VARCHAR(64) NOT NULL, | ||
203 | FOREIGN KEY (`adverb_id`) REFERENCES `adverbs`(`adverb_id`) | ||
204 | ); | ||
diff --git a/verbly/adjective.cpp b/verbly/adjective.cpp new file mode 100644 index 0000000..0f4087f --- /dev/null +++ b/verbly/adjective.cpp | |||
@@ -0,0 +1,586 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | adjective::adjective(const data& _data, int _id) : word(_data, _id) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | std::string adjective::base_form() const | ||
11 | { | ||
12 | return _base_form; | ||
13 | } | ||
14 | |||
15 | std::string adjective::comparative_form() const | ||
16 | { | ||
17 | return _comparative_form; | ||
18 | } | ||
19 | |||
20 | std::string adjective::superlative_form() const | ||
21 | { | ||
22 | return _superlative_form; | ||
23 | } | ||
24 | |||
25 | adjective::positioning adjective::position() const | ||
26 | { | ||
27 | return _position; | ||
28 | } | ||
29 | |||
30 | bool adjective::has_comparative_form() const | ||
31 | { | ||
32 | return !_comparative_form.empty(); | ||
33 | } | ||
34 | |||
35 | bool adjective::has_superlative_form() const | ||
36 | { | ||
37 | return !_superlative_form.empty(); | ||
38 | } | ||
39 | |||
40 | bool adjective::has_position() const | ||
41 | { | ||
42 | return _position != adjective::positioning::undefined; | ||
43 | } | ||
44 | |||
45 | adjective_query adjective::antonyms() const | ||
46 | { | ||
47 | return _data.adjectives().antonym_of(*this); | ||
48 | } | ||
49 | |||
50 | adjective_query adjective::synonyms() const | ||
51 | { | ||
52 | return _data.adjectives().synonym_of(*this); | ||
53 | } | ||
54 | |||
55 | adjective_query adjective::generalizations() const | ||
56 | { | ||
57 | return _data.adjectives().generalization_of(*this); | ||
58 | } | ||
59 | |||
60 | adjective_query adjective::specifications() const | ||
61 | { | ||
62 | return _data.adjectives().specification_of(*this); | ||
63 | } | ||
64 | |||
65 | noun_query adjective::anti_pertainyms() const | ||
66 | { | ||
67 | return _data.nouns().anti_pertainym_of(*this); | ||
68 | } | ||
69 | |||
70 | adverb_query adjective::mannernyms() const | ||
71 | { | ||
72 | return _data.adverbs().mannernym_of(*this); | ||
73 | } | ||
74 | |||
75 | noun_query adjective::attributes() const | ||
76 | { | ||
77 | return _data.nouns().attribute_of(*this); | ||
78 | } | ||
79 | |||
80 | adjective_query::adjective_query(const data& _data) : _data(_data) | ||
81 | { | ||
82 | |||
83 | } | ||
84 | |||
85 | adjective_query& adjective_query::limit(int _limit) | ||
86 | { | ||
87 | if ((_limit > 0) || (_limit == unlimited)) | ||
88 | { | ||
89 | this->_limit = _limit; | ||
90 | } | ||
91 | |||
92 | return *this; | ||
93 | } | ||
94 | |||
95 | adjective_query& adjective_query::random(bool _random) | ||
96 | { | ||
97 | this->_random = _random; | ||
98 | |||
99 | return *this; | ||
100 | } | ||
101 | |||
102 | adjective_query& adjective_query::except(const adjective& _word) | ||
103 | { | ||
104 | _except.push_back(_word); | ||
105 | |||
106 | return *this; | ||
107 | } | ||
108 | |||
109 | adjective_query& adjective_query::rhymes_with(const word& _word) | ||
110 | { | ||
111 | for (auto rhyme : _word.rhyme_phonemes()) | ||
112 | { | ||
113 | _rhymes.push_back(rhyme); | ||
114 | } | ||
115 | |||
116 | if (dynamic_cast<const adjective*>(&_word) != nullptr) | ||
117 | { | ||
118 | _except.push_back(dynamic_cast<const adjective&>(_word)); | ||
119 | } | ||
120 | |||
121 | return *this; | ||
122 | } | ||
123 | |||
124 | adjective_query& adjective_query::has_pronunciation(bool _has_prn) | ||
125 | { | ||
126 | this->_has_prn = _has_prn; | ||
127 | |||
128 | return *this; | ||
129 | } | ||
130 | |||
131 | adjective_query& adjective_query::is_variant(bool _is_variant) | ||
132 | { | ||
133 | this->_is_variant = _is_variant; | ||
134 | |||
135 | return *this; | ||
136 | } | ||
137 | |||
138 | adjective_query& adjective_query::variant_of(const noun& _noun) | ||
139 | { | ||
140 | _variant_of.push_back(_noun); | ||
141 | |||
142 | return *this; | ||
143 | } | ||
144 | |||
145 | adjective_query& adjective_query::not_variant_of(const noun& _noun) | ||
146 | { | ||
147 | _not_variant_of.push_back(_noun); | ||
148 | |||
149 | return *this; | ||
150 | } | ||
151 | |||
152 | adjective_query& adjective_query::has_antonyms(bool _is_antonymic) | ||
153 | { | ||
154 | this->_is_antonymic = _is_antonymic; | ||
155 | |||
156 | return *this; | ||
157 | } | ||
158 | |||
159 | adjective_query& adjective_query::antonym_of(const adjective& _adj) | ||
160 | { | ||
161 | _antonym_of.push_back(_adj); | ||
162 | |||
163 | return *this; | ||
164 | } | ||
165 | |||
166 | adjective_query& adjective_query::not_antonym_of(const adjective& _adj) | ||
167 | { | ||
168 | _not_antonym_of.push_back(_adj); | ||
169 | |||
170 | return *this; | ||
171 | } | ||
172 | |||
173 | adjective_query& adjective_query::has_synonyms(bool _is_synonymic) | ||
174 | { | ||
175 | this->_is_synonymic = _is_synonymic; | ||
176 | |||
177 | return *this; | ||
178 | } | ||
179 | |||
180 | adjective_query& adjective_query::synonym_of(const adjective& _adj) | ||
181 | { | ||
182 | _synonym_of.push_back(_adj); | ||
183 | |||
184 | return *this; | ||
185 | } | ||
186 | |||
187 | adjective_query& adjective_query::not_synonym_of(const adjective& _adj) | ||
188 | { | ||
189 | _not_synonym_of.push_back(_adj); | ||
190 | |||
191 | return *this; | ||
192 | } | ||
193 | |||
194 | adjective_query& adjective_query::is_generalization(bool _is_generalization) | ||
195 | { | ||
196 | this->_is_generalization = _is_generalization; | ||
197 | |||
198 | return *this; | ||
199 | } | ||
200 | |||
201 | adjective_query& adjective_query::generalization_of(const adjective& _adj) | ||
202 | { | ||
203 | _generalization_of.push_back(_adj); | ||
204 | |||
205 | return *this; | ||
206 | } | ||
207 | |||
208 | adjective_query& adjective_query::not_generalization_of(const adjective& _adj) | ||
209 | { | ||
210 | _not_generalization_of.push_back(_adj); | ||
211 | |||
212 | return *this; | ||
213 | } | ||
214 | |||
215 | adjective_query& adjective_query::is_specification(bool _is_specification) | ||
216 | { | ||
217 | this->_is_specification = _is_specification; | ||
218 | |||
219 | return *this; | ||
220 | } | ||
221 | |||
222 | adjective_query& adjective_query::specification_of(const adjective& _adj) | ||
223 | { | ||
224 | _specification_of.push_back(_adj); | ||
225 | |||
226 | return *this; | ||
227 | } | ||
228 | |||
229 | adjective_query& adjective_query::not_specification_of(const adjective& _adj) | ||
230 | { | ||
231 | _not_specification_of.push_back(_adj); | ||
232 | |||
233 | return *this; | ||
234 | } | ||
235 | |||
236 | adjective_query& adjective_query::is_pertainymic(bool _is_pertainymic) | ||
237 | { | ||
238 | this->_is_pertainymic = _is_pertainymic; | ||
239 | |||
240 | return *this; | ||
241 | } | ||
242 | |||
243 | adjective_query& adjective_query::pertainym_of(const noun& _noun) | ||
244 | { | ||
245 | _pertainym_of.push_back(_noun); | ||
246 | |||
247 | return *this; | ||
248 | } | ||
249 | |||
250 | adjective_query& adjective_query::is_mannernymic(bool _is_mannernymic) | ||
251 | { | ||
252 | this->_is_mannernymic = _is_mannernymic; | ||
253 | |||
254 | return *this; | ||
255 | } | ||
256 | |||
257 | adjective_query& adjective_query::anti_mannernym_of(const adverb& _adv) | ||
258 | { | ||
259 | _anti_mannernym_of.push_back(_adv); | ||
260 | |||
261 | return *this; | ||
262 | } | ||
263 | |||
264 | std::list<adjective> adjective_query::run() const | ||
265 | { | ||
266 | std::stringstream construct; | ||
267 | construct << "SELECT adjective_id, base_form, comparative, superlative, position FROM adjectives"; | ||
268 | std::list<std::string> conditions; | ||
269 | |||
270 | if (_has_prn) | ||
271 | { | ||
272 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM adjective_pronunciations)"); | ||
273 | } | ||
274 | |||
275 | if (!_rhymes.empty()) | ||
276 | { | ||
277 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
278 | std::string cond = "adjective_id IN (SELECT adjective_id FROM adjective_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
279 | conditions.push_back(cond); | ||
280 | } | ||
281 | |||
282 | for (auto except : _except) | ||
283 | { | ||
284 | conditions.push_back("adjective_id != @EXCID"); | ||
285 | } | ||
286 | |||
287 | if (_requires_comparative_form) | ||
288 | { | ||
289 | conditions.push_back("comparative IS NOT NULL"); | ||
290 | } | ||
291 | |||
292 | if (_requires_superlative_form) | ||
293 | { | ||
294 | conditions.push_back("superlative IS NOT NULL"); | ||
295 | } | ||
296 | |||
297 | if (_position != adjective::positioning::undefined) | ||
298 | { | ||
299 | switch (_position) | ||
300 | { | ||
301 | case adjective::positioning::predicate: conditions.push_back("position = 'p'"); break; | ||
302 | case adjective::positioning::attributive: conditions.push_back("position = 'a'"); break; | ||
303 | case adjective::positioning::postnominal: conditions.push_back("position = 'i'"); break; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | if (_is_variant) | ||
308 | { | ||
309 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM variation)"); | ||
310 | } | ||
311 | |||
312 | if (!_variant_of.empty()) | ||
313 | { | ||
314 | std::list<std::string> clauses(_variant_of.size(), "noun_id = @ATTRID"); | ||
315 | std::string cond = "adjective_id IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
316 | conditions.push_back(cond); | ||
317 | } | ||
318 | |||
319 | if (!_not_variant_of.empty()) | ||
320 | { | ||
321 | std::list<std::string> clauses(_not_variant_of.size(), "noun_id = @NATTRID"); | ||
322 | std::string cond = "adjective_id NOT IN (SELECT adjective_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
323 | conditions.push_back(cond); | ||
324 | } | ||
325 | |||
326 | if (_is_antonymic) | ||
327 | { | ||
328 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); | ||
329 | } | ||
330 | |||
331 | if (!_antonym_of.empty()) | ||
332 | { | ||
333 | std::list<std::string> clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); | ||
334 | std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
335 | conditions.push_back(cond); | ||
336 | } | ||
337 | |||
338 | if (!_not_antonym_of.empty()) | ||
339 | { | ||
340 | std::list<std::string> clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); | ||
341 | std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
342 | conditions.push_back(cond); | ||
343 | } | ||
344 | |||
345 | if (_is_synonymic) | ||
346 | { | ||
347 | conditions.push_back("adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); | ||
348 | } | ||
349 | |||
350 | if (!_synonym_of.empty()) | ||
351 | { | ||
352 | std::list<std::string> clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); | ||
353 | std::string cond = "adjective_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
354 | conditions.push_back(cond); | ||
355 | } | ||
356 | |||
357 | if (!_not_synonym_of.empty()) | ||
358 | { | ||
359 | std::list<std::string> clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); | ||
360 | std::string cond = "adjective_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
361 | conditions.push_back(cond); | ||
362 | } | ||
363 | |||
364 | if (_is_generalization) | ||
365 | { | ||
366 | conditions.push_back("adjective_id IN (SELECT general_id FROM specification)"); | ||
367 | } | ||
368 | |||
369 | if (!_generalization_of.empty()) | ||
370 | { | ||
371 | std::list<std::string> clauses(_generalization_of.size(), "specific_id = @SPECID"); | ||
372 | std::string cond = "adjective_id IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
373 | conditions.push_back(cond); | ||
374 | } | ||
375 | |||
376 | if (!_not_generalization_of.empty()) | ||
377 | { | ||
378 | std::list<std::string> clauses(_not_generalization_of.size(), "specific_id = @NSPECID"); | ||
379 | std::string cond = "adjective_id NOT IN (SELECT general_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
380 | conditions.push_back(cond); | ||
381 | } | ||
382 | |||
383 | if (_is_specification) | ||
384 | { | ||
385 | conditions.push_back("adjective_id IN (SELECT specific_id FROM specification)"); | ||
386 | } | ||
387 | |||
388 | if (!_specification_of.empty()) | ||
389 | { | ||
390 | std::list<std::string> clauses(_specification_of.size(), "general_id = @GENID"); | ||
391 | std::string cond = "adjective_id IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
392 | conditions.push_back(cond); | ||
393 | } | ||
394 | |||
395 | if (!_not_specification_of.empty()) | ||
396 | { | ||
397 | std::list<std::string> clauses(_not_specification_of.size(), "general_id = @NGENID"); | ||
398 | std::string cond = "adjective_id NOT IN (SELECT specific_id FROM specification WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
399 | conditions.push_back(cond); | ||
400 | } | ||
401 | |||
402 | if (_is_pertainymic) | ||
403 | { | ||
404 | conditions.push_back("adjective_id IN (SELECT pertainym_id FROM pertainymy)"); | ||
405 | } | ||
406 | |||
407 | if (!_pertainym_of.empty()) | ||
408 | { | ||
409 | std::list<std::string> clauses(_pertainym_of.size(), "noun_id = @APERID"); | ||
410 | std::string cond = "adjective_id IN (SELECT pertainym_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
411 | conditions.push_back(cond); | ||
412 | } | ||
413 | |||
414 | if (_is_mannernymic) | ||
415 | { | ||
416 | conditions.push_back("adjective_id IN (SELECT adjective_id FROM mannernymy)"); | ||
417 | } | ||
418 | |||
419 | if (!_anti_mannernym_of.empty()) | ||
420 | { | ||
421 | std::list<std::string> clauses(_anti_mannernym_of.size(), "mannernym_id = @MANID"); | ||
422 | std::string cond = "adjective_id IN (SELECT adjective_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
423 | conditions.push_back(cond); | ||
424 | } | ||
425 | |||
426 | if (!conditions.empty()) | ||
427 | { | ||
428 | construct << " WHERE "; | ||
429 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
430 | } | ||
431 | |||
432 | if (_random) | ||
433 | { | ||
434 | construct << " ORDER BY RANDOM()"; | ||
435 | } | ||
436 | |||
437 | if (_limit != unlimited) | ||
438 | { | ||
439 | construct << " LIMIT " << _limit; | ||
440 | } | ||
441 | |||
442 | sqlite3_stmt* ppstmt; | ||
443 | std::string query = construct.str(); | ||
444 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
445 | { | ||
446 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
447 | } | ||
448 | |||
449 | if (!_rhymes.empty()) | ||
450 | { | ||
451 | int i = 0; | ||
452 | for (auto rhyme : _rhymes) | ||
453 | { | ||
454 | std::string rhymer = "%" + rhyme; | ||
455 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
456 | |||
457 | i++; | ||
458 | } | ||
459 | } | ||
460 | |||
461 | for (auto except : _except) | ||
462 | { | ||
463 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
464 | } | ||
465 | |||
466 | for (auto attribute : _variant_of) | ||
467 | { | ||
468 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ATTRID"), attribute._id); | ||
469 | } | ||
470 | |||
471 | for (auto attribute : _not_variant_of) | ||
472 | { | ||
473 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NATTRID"), attribute._id); | ||
474 | } | ||
475 | |||
476 | for (auto antonym : _antonym_of) | ||
477 | { | ||
478 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
479 | } | ||
480 | |||
481 | for (auto antonym : _not_antonym_of) | ||
482 | { | ||
483 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
484 | } | ||
485 | |||
486 | for (auto synonym : _synonym_of) | ||
487 | { | ||
488 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
489 | } | ||
490 | |||
491 | for (auto synonym : _not_synonym_of) | ||
492 | { | ||
493 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
494 | } | ||
495 | |||
496 | for (auto specific : _generalization_of) | ||
497 | { | ||
498 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SPECID"), specific._id); | ||
499 | } | ||
500 | |||
501 | for (auto specific : _not_generalization_of) | ||
502 | { | ||
503 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSPECID"), specific._id); | ||
504 | } | ||
505 | |||
506 | for (auto general : _specification_of) | ||
507 | { | ||
508 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@GENID"), general._id); | ||
509 | } | ||
510 | |||
511 | for (auto general : _not_specification_of) | ||
512 | { | ||
513 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NGENID"), general._id); | ||
514 | } | ||
515 | |||
516 | for (auto n : _pertainym_of) | ||
517 | { | ||
518 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@APERID"), n._id); | ||
519 | } | ||
520 | |||
521 | for (auto mannernym : _anti_mannernym_of) | ||
522 | { | ||
523 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MANID"), mannernym._id); | ||
524 | } | ||
525 | |||
526 | std::list<adjective> output; | ||
527 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
528 | { | ||
529 | adjective tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
530 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
531 | |||
532 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
533 | { | ||
534 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
535 | } | ||
536 | |||
537 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
538 | { | ||
539 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
540 | } | ||
541 | |||
542 | if (sqlite3_column_type(ppstmt, 4) != SQLITE_NULL) | ||
543 | { | ||
544 | std::string adjpos(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
545 | if (adjpos == "p") | ||
546 | { | ||
547 | tnc._position = adjective::positioning::predicate; | ||
548 | } else if (adjpos == "a") | ||
549 | { | ||
550 | tnc._position = adjective::positioning::attributive; | ||
551 | } else if (adjpos == "i") | ||
552 | { | ||
553 | tnc._position = adjective::positioning::postnominal; | ||
554 | } | ||
555 | } | ||
556 | |||
557 | output.push_back(tnc); | ||
558 | } | ||
559 | |||
560 | sqlite3_finalize(ppstmt); | ||
561 | |||
562 | for (auto& adjective : output) | ||
563 | { | ||
564 | query = "SELECT pronunciation FROM adjective_pronunciations WHERE adjective_id = ?"; | ||
565 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
566 | { | ||
567 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
568 | } | ||
569 | |||
570 | sqlite3_bind_int(ppstmt, 1, adjective._id); | ||
571 | |||
572 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
573 | { | ||
574 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
575 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
576 | |||
577 | adjective.pronunciations.push_back(phonemes); | ||
578 | } | ||
579 | |||
580 | sqlite3_finalize(ppstmt); | ||
581 | } | ||
582 | |||
583 | return output; | ||
584 | } | ||
585 | |||
586 | }; | ||
diff --git a/verbly/adjective.h b/verbly/adjective.h index 9d7883f..4927d59 100644 --- a/verbly/adjective.h +++ b/verbly/adjective.h | |||
@@ -3,17 +3,129 @@ | |||
3 | 3 | ||
4 | namespace verbly { | 4 | namespace verbly { |
5 | 5 | ||
6 | class adjective { | 6 | class adjective_query; |
7 | class adverb_query; | ||
8 | class noun_query; | ||
9 | |||
10 | class adjective : public word { | ||
11 | public: | ||
12 | enum class positioning { | ||
13 | undefined, | ||
14 | predicate, | ||
15 | attributive, | ||
16 | postnominal | ||
17 | }; | ||
18 | |||
7 | private: | 19 | private: |
8 | int id; | 20 | std::string _base_form; |
21 | std::string _comparative_form; | ||
22 | std::string _superlative_form; | ||
23 | positioning _position = positioning::undefined; | ||
24 | |||
25 | friend class adjective_query; | ||
26 | |||
27 | public: | ||
28 | adjective(const data& _data, int _id); | ||
29 | |||
30 | std::string base_form() const; | ||
31 | std::string comparative_form() const; | ||
32 | std::string superlative_form() const; | ||
33 | positioning position() const; | ||
34 | |||
35 | bool has_comparative_form() const; | ||
36 | bool has_superlative_form() const; | ||
37 | bool has_position() const; | ||
9 | 38 | ||
39 | adjective_query antonyms() const; | ||
40 | adjective_query synonyms() const; | ||
41 | adjective_query generalizations() const; | ||
42 | adjective_query specifications() const; | ||
43 | noun_query anti_pertainyms() const; | ||
44 | adverb_query mannernyms() const; | ||
45 | noun_query attributes() const; | ||
46 | }; | ||
47 | |||
48 | class adjective_query { | ||
10 | public: | 49 | public: |
11 | std::string form; | 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 | std::list<adjective> run() const; | ||
89 | |||
90 | const static int unlimited = -1; | ||
91 | |||
92 | protected: | ||
93 | const data& _data; | ||
94 | int _limit = unlimited; | ||
95 | bool _random = false; | ||
96 | std::list<std::string> _rhymes; | ||
97 | std::list<adjective> _except; | ||
98 | bool _has_prn = false; | ||
99 | |||
100 | bool _requires_comparative_form = false; | ||
101 | bool _requires_superlative_form = false; | ||
102 | adjective::positioning _position = adjective::positioning::undefined; | ||
103 | |||
104 | bool _is_variant = false; | ||
105 | std::list<noun> _variant_of; | ||
106 | std::list<noun> _not_variant_of; | ||
107 | |||
108 | bool _is_antonymic = false; | ||
109 | std::list<adjective> _antonym_of; | ||
110 | std::list<adjective> _not_antonym_of; | ||
111 | |||
112 | bool _is_synonymic = false; | ||
113 | std::list<adjective> _synonym_of; | ||
114 | std::list<adjective> _not_synonym_of; | ||
115 | |||
116 | bool _is_generalization = false; | ||
117 | std::list<adjective> _generalization_of; | ||
118 | std::list<adjective> _not_generalization_of; | ||
119 | |||
120 | bool _is_specification = false; | ||
121 | std::list<adjective> _specification_of; | ||
122 | std::list<adjective> _not_specification_of; | ||
123 | |||
124 | bool _is_pertainymic = false; | ||
125 | std::list<noun> _pertainym_of; | ||
12 | 126 | ||
13 | adjective(int id) : id(id) | 127 | bool _is_mannernymic = false; |
14 | { | 128 | std::list<adverb> _anti_mannernym_of; |
15 | |||
16 | } | ||
17 | }; | 129 | }; |
18 | 130 | ||
19 | }; | 131 | }; |
diff --git a/verbly/adverb.cpp b/verbly/adverb.cpp new file mode 100644 index 0000000..9bb5a0d --- /dev/null +++ b/verbly/adverb.cpp | |||
@@ -0,0 +1,364 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | adverb::adverb(const data& _data, int _id) : word(_data, _id) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | std::string adverb::base_form() const | ||
11 | { | ||
12 | return _base_form; | ||
13 | } | ||
14 | |||
15 | std::string adverb::comparative_form() const | ||
16 | { | ||
17 | return _comparative_form; | ||
18 | } | ||
19 | |||
20 | std::string adverb::superlative_form() const | ||
21 | { | ||
22 | return _superlative_form; | ||
23 | } | ||
24 | |||
25 | bool adverb::has_comparative_form() const | ||
26 | { | ||
27 | return !_comparative_form.empty(); | ||
28 | } | ||
29 | |||
30 | bool adverb::has_superlative_form() const | ||
31 | { | ||
32 | return !_superlative_form.empty(); | ||
33 | } | ||
34 | |||
35 | adverb_query adverb::antonyms() const | ||
36 | { | ||
37 | return _data.adverbs().antonym_of(*this); | ||
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 | |||
76 | return *this; | ||
77 | } | ||
78 | |||
79 | adverb_query& adverb_query::rhymes_with(const word& _word) | ||
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 | std::list<adverb> adverb_query::run() const | ||
172 | { | ||
173 | std::stringstream construct; | ||
174 | construct << "SELECT adverb_id, base_form, comparative, superlative FROM adverbs"; | ||
175 | std::list<std::string> conditions; | ||
176 | |||
177 | if (_has_prn) | ||
178 | { | ||
179 | conditions.push_back("adverb_id IN (SELECT adverb_id FROM adverb_pronunciations)"); | ||
180 | } | ||
181 | |||
182 | if (!_rhymes.empty()) | ||
183 | { | ||
184 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
185 | std::string cond = "adverb_id IN (SELECT adverb_id FROM adverb_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
186 | conditions.push_back(cond); | ||
187 | } | ||
188 | |||
189 | for (auto except : _except) | ||
190 | { | ||
191 | conditions.push_back("adverb_id != @EXCID"); | ||
192 | } | ||
193 | |||
194 | if (_requires_comparative_form) | ||
195 | { | ||
196 | conditions.push_back("comparative IS NOT NULL"); | ||
197 | } | ||
198 | |||
199 | if (_requires_superlative_form) | ||
200 | { | ||
201 | conditions.push_back("superlative IS NOT NULL"); | ||
202 | } | ||
203 | |||
204 | if (_has_antonyms) | ||
205 | { | ||
206 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy)"); | ||
207 | } | ||
208 | |||
209 | if (!_antonym_of.empty()) | ||
210 | { | ||
211 | std::list<std::string> clauses(_antonym_of.size(), "adverb_1_id = @ANTID"); | ||
212 | std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
213 | conditions.push_back(cond); | ||
214 | } | ||
215 | |||
216 | if (!_not_antonym_of.empty()) | ||
217 | { | ||
218 | std::list<std::string> clauses(_not_antonym_of.size(), "adverb_1_id = @NANTID"); | ||
219 | std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
220 | conditions.push_back(cond); | ||
221 | } | ||
222 | |||
223 | if (_has_synonyms) | ||
224 | { | ||
225 | conditions.push_back("adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy)"); | ||
226 | } | ||
227 | |||
228 | if (!_synonym_of.empty()) | ||
229 | { | ||
230 | std::list<std::string> clauses(_synonym_of.size(), "adverb_1_id = @SYNID"); | ||
231 | std::string cond = "adverb_id IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
232 | conditions.push_back(cond); | ||
233 | } | ||
234 | |||
235 | if (!_not_synonym_of.empty()) | ||
236 | { | ||
237 | std::list<std::string> clauses(_not_synonym_of.size(), "adverb_1_id = @NSYNID"); | ||
238 | std::string cond = "adverb_id NOT IN (SELECT adverb_2_id FROM adverb_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
239 | conditions.push_back(cond); | ||
240 | } | ||
241 | |||
242 | if (_is_mannernymic) | ||
243 | { | ||
244 | conditions.push_back("adverb_id IN (SELECT mannernym_id FROM mannernymy)"); | ||
245 | } | ||
246 | |||
247 | if (!_mannernym_of.empty()) | ||
248 | { | ||
249 | std::list<std::string> clauses(_mannernym_of.size(), "adjective_id = @AMANID"); | ||
250 | std::string cond = "adverb_id IN (SELECT mannernym_id FROM mannernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
251 | conditions.push_back(cond); | ||
252 | } | ||
253 | |||
254 | if (!conditions.empty()) | ||
255 | { | ||
256 | construct << " WHERE "; | ||
257 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
258 | } | ||
259 | |||
260 | if (_random) | ||
261 | { | ||
262 | construct << " ORDER BY RANDOM()"; | ||
263 | } | ||
264 | |||
265 | if (_limit != unlimited) | ||
266 | { | ||
267 | construct << " LIMIT " << _limit; | ||
268 | } | ||
269 | |||
270 | sqlite3_stmt* ppstmt; | ||
271 | std::string query = construct.str(); | ||
272 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
273 | { | ||
274 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
275 | } | ||
276 | |||
277 | if (!_rhymes.empty()) | ||
278 | { | ||
279 | int i = 0; | ||
280 | for (auto rhyme : _rhymes) | ||
281 | { | ||
282 | std::string rhymer = "%" + rhyme; | ||
283 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
284 | |||
285 | i++; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | for (auto except : _except) | ||
290 | { | ||
291 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
292 | } | ||
293 | |||
294 | for (auto antonym : _antonym_of) | ||
295 | { | ||
296 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
297 | } | ||
298 | |||
299 | for (auto antonym : _not_antonym_of) | ||
300 | { | ||
301 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
302 | } | ||
303 | |||
304 | for (auto synonym : _synonym_of) | ||
305 | { | ||
306 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
307 | } | ||
308 | |||
309 | for (auto synonym : _not_synonym_of) | ||
310 | { | ||
311 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
312 | } | ||
313 | |||
314 | for (auto adj : _mannernym_of) | ||
315 | { | ||
316 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@AMANID"), adj._id); | ||
317 | } | ||
318 | |||
319 | std::list<adverb> output; | ||
320 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
321 | { | ||
322 | adverb tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
323 | tnc._base_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
324 | |||
325 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
326 | { | ||
327 | tnc._comparative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
328 | } | ||
329 | |||
330 | if (sqlite3_column_type(ppstmt, 3) != SQLITE_NULL) | ||
331 | { | ||
332 | tnc._superlative_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
333 | } | ||
334 | |||
335 | output.push_back(tnc); | ||
336 | } | ||
337 | |||
338 | sqlite3_finalize(ppstmt); | ||
339 | |||
340 | for (auto& adverb : output) | ||
341 | { | ||
342 | query = "SELECT pronunciation FROM adverb_pronunciations WHERE adverb_id = ?"; | ||
343 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
344 | { | ||
345 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
346 | } | ||
347 | |||
348 | sqlite3_bind_int(ppstmt, 1, adverb._id); | ||
349 | |||
350 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
351 | { | ||
352 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
353 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
354 | |||
355 | adverb.pronunciations.push_back(phonemes); | ||
356 | } | ||
357 | |||
358 | sqlite3_finalize(ppstmt); | ||
359 | } | ||
360 | |||
361 | return output; | ||
362 | } | ||
363 | |||
364 | }; | ||
diff --git a/verbly/adverb.h b/verbly/adverb.h index 6d2466e..42c3492 100644 --- a/verbly/adverb.h +++ b/verbly/adverb.h | |||
@@ -3,17 +3,78 @@ | |||
3 | 3 | ||
4 | namespace verbly { | 4 | namespace verbly { |
5 | 5 | ||
6 | class adverb { | 6 | class adverb : public word { |
7 | private: | 7 | private: |
8 | int id; | 8 | std::string _base_form; |
9 | std::string _comparative_form; | ||
10 | std::string _superlative_form; | ||
9 | 11 | ||
12 | friend class adverb_query; | ||
13 | |||
14 | public: | ||
15 | adverb(const data& _data, int _id); | ||
16 | |||
17 | std::string base_form() const; | ||
18 | std::string comparative_form() const; | ||
19 | std::string superlative_form() const; | ||
20 | |||
21 | bool has_comparative_form() const; | ||
22 | bool has_superlative_form() const; | ||
23 | |||
24 | adverb_query antonyms() const; | ||
25 | adverb_query synonyms() const; | ||
26 | adjective_query anti_mannernyms() const; | ||
27 | }; | ||
28 | |||
29 | class adverb_query { | ||
10 | public: | 30 | public: |
11 | std::string form; | 31 | adverb_query(const data& _data); |
32 | |||
33 | adverb_query& limit(int _limit); | ||
34 | adverb_query& random(bool _random); | ||
35 | adverb_query& except(const adverb& _word); | ||
36 | adverb_query& rhymes_with(const word& _word); | ||
37 | adverb_query& has_pronunciation(bool _has_prn); | ||
38 | |||
39 | adverb_query& requires_comparative_form(bool _arg); | ||
40 | adverb_query& requires_superlative_form(bool _arg); | ||
41 | |||
42 | adverb_query& has_antonyms(bool _arg); | ||
43 | adverb_query& antonym_of(const adverb& _adv); | ||
44 | adverb_query& not_antonym_of(const adverb& _adv); | ||
45 | |||
46 | adverb_query& has_synonyms(bool _arg); | ||
47 | adverb_query& synonym_of(const adverb& _adv); | ||
48 | adverb_query& not_synonym_of(const adverb& _adv); | ||
49 | |||
50 | adverb_query& is_mannernymic(bool _arg); | ||
51 | adverb_query& mannernym_of(const adjective& _adj); | ||
52 | |||
53 | std::list<adverb> run() const; | ||
54 | |||
55 | const static int unlimited = -1; | ||
56 | |||
57 | private: | ||
58 | const data& _data; | ||
59 | int _limit = unlimited; | ||
60 | bool _random = false; | ||
61 | std::list<std::string> _rhymes; | ||
62 | std::list<adverb> _except; | ||
63 | bool _has_prn = false; | ||
64 | |||
65 | bool _requires_comparative_form = false; | ||
66 | bool _requires_superlative_form = false; | ||
67 | |||
68 | bool _has_antonyms = false; | ||
69 | std::list<adverb> _antonym_of; | ||
70 | std::list<adverb> _not_antonym_of; | ||
71 | |||
72 | bool _has_synonyms = false; | ||
73 | std::list<adverb> _synonym_of; | ||
74 | std::list<adverb> _not_synonym_of; | ||
12 | 75 | ||
13 | adverb(int id) : id(id) | 76 | bool _is_mannernymic = false; |
14 | { | 77 | std::list<adjective> _mannernym_of; |
15 | |||
16 | } | ||
17 | }; | 78 | }; |
18 | 79 | ||
19 | }; | 80 | }; |
diff --git a/verbly/data.cpp b/verbly/data.cpp new file mode 100644 index 0000000..57a8850 --- /dev/null +++ b/verbly/data.cpp | |||
@@ -0,0 +1,50 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | data::data(std::string datafile) | ||
6 | { | ||
7 | if (sqlite3_open_v2(datafile.c_str(), &ppdb, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) | ||
8 | { | ||
9 | throw std::invalid_argument(sqlite3_errmsg(ppdb)); | ||
10 | } | ||
11 | } | ||
12 | |||
13 | data::data(data&& other) | ||
14 | { | ||
15 | ppdb = other.ppdb; | ||
16 | } | ||
17 | |||
18 | data& data::operator=(data&& other) | ||
19 | { | ||
20 | ppdb = other.ppdb; | ||
21 | |||
22 | return *this; | ||
23 | } | ||
24 | |||
25 | data::~data() | ||
26 | { | ||
27 | sqlite3_close_v2(ppdb); | ||
28 | } | ||
29 | |||
30 | verb_query data::verbs() const | ||
31 | { | ||
32 | return verb_query(*this); | ||
33 | } | ||
34 | |||
35 | adjective_query data::adjectives() const | ||
36 | { | ||
37 | return adjective_query(*this); | ||
38 | } | ||
39 | |||
40 | adverb_query data::adverbs() const | ||
41 | { | ||
42 | return adverb_query(*this); | ||
43 | } | ||
44 | |||
45 | noun_query data::nouns() const | ||
46 | { | ||
47 | return noun_query(*this); | ||
48 | } | ||
49 | |||
50 | }; | ||
diff --git a/verbly/data.h b/verbly/data.h index e901cba..37092d7 100644 --- a/verbly/data.h +++ b/verbly/data.h | |||
@@ -1,273 +1,46 @@ | |||
1 | #ifndef DATA_H_C4AEC3DD | 1 | #ifndef DATA_H_C4AEC3DD |
2 | #define DATA_H_C4AEC3DD | 2 | #define DATA_H_C4AEC3DD |
3 | 3 | ||
4 | #include "verb.h" | ||
5 | #include <sqlite3.h> | 4 | #include <sqlite3.h> |
6 | #include <stdexcept> | 5 | #include <stdexcept> |
7 | 6 | ||
8 | namespace verbly { | 7 | namespace verbly { |
9 | 8 | ||
9 | class data; | ||
10 | class word; | ||
11 | class adjective; | ||
12 | class noun; | ||
13 | class verb; | ||
14 | class adverb; | ||
15 | class adjective_query; | ||
16 | class adverb_query; | ||
17 | class noun_query; | ||
18 | class verb_query; | ||
19 | |||
10 | class data { | 20 | class data { |
11 | private: | 21 | private: |
12 | sqlite3* ppdb; | 22 | sqlite3* ppdb; |
13 | 23 | ||
14 | public: | 24 | friend class adjective_query; |
15 | class verb_query { | 25 | friend class noun_query; |
16 | public: | 26 | friend class verb_query; |
17 | const static int unlimited = -1; | 27 | friend class adverb_query; |
18 | |||
19 | private: | ||
20 | const data& database; | ||
21 | int m_limit = unlimited; | ||
22 | bool m_random = false; | ||
23 | |||
24 | public: | ||
25 | verb_query(const data& database) : database(database) | ||
26 | { | ||
27 | |||
28 | } | ||
29 | |||
30 | verb_query& limit(int m_limit) | ||
31 | { | ||
32 | if ((m_limit > 0) || (m_limit == unlimited)) | ||
33 | { | ||
34 | this->m_limit = m_limit; | ||
35 | } | ||
36 | |||
37 | return *this; | ||
38 | } | ||
39 | |||
40 | verb_query& random(bool m_random) | ||
41 | { | ||
42 | this->m_random = m_random; | ||
43 | |||
44 | return *this; | ||
45 | } | ||
46 | |||
47 | std::list<verb> run() const | ||
48 | { | ||
49 | std::stringstream construct; | ||
50 | construct << "SELECT verb_id, infinitive, past_tense, past_participle, ing_form, s_form FROM verbs"; | ||
51 | |||
52 | if (m_random) | ||
53 | { | ||
54 | construct << " ORDER BY RANDOM()"; | ||
55 | } | ||
56 | |||
57 | if (m_limit != unlimited) | ||
58 | { | ||
59 | construct << " LIMIT " << m_limit; | ||
60 | } | ||
61 | |||
62 | sqlite3_stmt* ppstmt; | ||
63 | std::string query = construct.str(); | ||
64 | if (sqlite3_prepare_v2(database.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
65 | { | ||
66 | throw std::runtime_error(sqlite3_errmsg(database.ppdb)); | ||
67 | } | ||
68 | |||
69 | std::list<verb> output; | ||
70 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
71 | { | ||
72 | verb tnc {sqlite3_column_int(ppstmt, 0)}; | ||
73 | tnc.infinitive = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
74 | tnc.past_tense = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
75 | tnc.past_participle = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 3))); | ||
76 | tnc.ing_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 4))); | ||
77 | tnc.s_form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 5))); | ||
78 | |||
79 | output.push_back(tnc); | ||
80 | } | ||
81 | |||
82 | sqlite3_finalize(ppstmt); | ||
83 | |||
84 | return output; | ||
85 | } | ||
86 | |||
87 | }; | ||
88 | |||
89 | class adjective_query { | ||
90 | public: | ||
91 | const static int unlimited = -1; | ||
92 | |||
93 | private: | ||
94 | const data& database; | ||
95 | int m_limit = unlimited; | ||
96 | bool m_random = false; | ||
97 | |||
98 | public: | ||
99 | adjective_query(const data& database) : database(database) | ||
100 | { | ||
101 | |||
102 | } | ||
103 | |||
104 | adjective_query& limit(int m_limit) | ||
105 | { | ||
106 | if ((m_limit > 0) || (m_limit == unlimited)) | ||
107 | { | ||
108 | this->m_limit = m_limit; | ||
109 | } | ||
110 | |||
111 | return *this; | ||
112 | } | ||
113 | |||
114 | adjective_query& random(bool m_random) | ||
115 | { | ||
116 | this->m_random = m_random; | ||
117 | |||
118 | return *this; | ||
119 | } | ||
120 | |||
121 | std::list<adjective> run() const | ||
122 | { | ||
123 | std::stringstream construct; | ||
124 | construct << "SELECT adjective_id, form FROM adjectives"; | ||
125 | |||
126 | if (m_random) | ||
127 | { | ||
128 | construct << " ORDER BY RANDOM()"; | ||
129 | } | ||
130 | |||
131 | if (m_limit != unlimited) | ||
132 | { | ||
133 | construct << " LIMIT " << m_limit; | ||
134 | } | ||
135 | |||
136 | sqlite3_stmt* ppstmt; | ||
137 | std::string query = construct.str(); | ||
138 | if (sqlite3_prepare_v2(database.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
139 | { | ||
140 | throw std::runtime_error(sqlite3_errmsg(database.ppdb)); | ||
141 | } | ||
142 | |||
143 | std::list<adjective> output; | ||
144 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
145 | { | ||
146 | adjective tnc {sqlite3_column_int(ppstmt, 0)}; | ||
147 | tnc.form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
148 | |||
149 | output.push_back(tnc); | ||
150 | } | ||
151 | |||
152 | sqlite3_finalize(ppstmt); | ||
153 | |||
154 | return output; | ||
155 | } | ||
156 | |||
157 | }; | ||
158 | |||
159 | class adverb_query { | ||
160 | public: | ||
161 | const static int unlimited = -1; | ||
162 | |||
163 | private: | ||
164 | const data& database; | ||
165 | int m_limit = unlimited; | ||
166 | bool m_random = false; | ||
167 | |||
168 | public: | ||
169 | adverb_query(const data& database) : database(database) | ||
170 | { | ||
171 | |||
172 | } | ||
173 | |||
174 | adverb_query& limit(int m_limit) | ||
175 | { | ||
176 | if ((m_limit > 0) || (m_limit == unlimited)) | ||
177 | { | ||
178 | this->m_limit = m_limit; | ||
179 | } | ||
180 | |||
181 | return *this; | ||
182 | } | ||
183 | |||
184 | adverb_query& random(bool m_random) | ||
185 | { | ||
186 | this->m_random = m_random; | ||
187 | |||
188 | return *this; | ||
189 | } | ||
190 | |||
191 | std::list<adverb> run() const | ||
192 | { | ||
193 | std::stringstream construct; | ||
194 | construct << "SELECT adverb_id, form FROM adverbs"; | ||
195 | |||
196 | if (m_random) | ||
197 | { | ||
198 | construct << " ORDER BY RANDOM()"; | ||
199 | } | ||
200 | |||
201 | if (m_limit != unlimited) | ||
202 | { | ||
203 | construct << " LIMIT " << m_limit; | ||
204 | } | ||
205 | |||
206 | sqlite3_stmt* ppstmt; | ||
207 | std::string query = construct.str(); | ||
208 | if (sqlite3_prepare_v2(database.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
209 | { | ||
210 | throw std::runtime_error(sqlite3_errmsg(database.ppdb)); | ||
211 | } | ||
212 | |||
213 | std::list<adverb> output; | ||
214 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
215 | { | ||
216 | adverb tnc {sqlite3_column_int(ppstmt, 0)}; | ||
217 | tnc.form = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
218 | |||
219 | output.push_back(tnc); | ||
220 | } | ||
221 | |||
222 | sqlite3_finalize(ppstmt); | ||
223 | |||
224 | return output; | ||
225 | } | ||
226 | |||
227 | }; | ||
228 | 28 | ||
229 | data(std::string datafile) | 29 | public: |
230 | { | 30 | data(std::string datafile); |
231 | if (sqlite3_open_v2(datafile.c_str(), &ppdb, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK) | ||
232 | { | ||
233 | throw std::invalid_argument(sqlite3_errmsg(ppdb)); | ||
234 | } | ||
235 | } | ||
236 | 31 | ||
237 | data(const data& other) = delete; | 32 | data(const data& other) = delete; |
238 | data& operator=(const data& other) = delete; | 33 | data& operator=(const data& other) = delete; |
239 | 34 | ||
240 | data(data&& other) | 35 | data(data&& other); |
241 | { | 36 | data& operator=(data&& other); |
242 | ppdb = other.ppdb; | ||
243 | } | ||
244 | |||
245 | data& operator=(data&& other) | ||
246 | { | ||
247 | ppdb = other.ppdb; | ||
248 | |||
249 | return *this; | ||
250 | } | ||
251 | |||
252 | ~data() | ||
253 | { | ||
254 | sqlite3_close_v2(ppdb); | ||
255 | } | ||
256 | |||
257 | verb_query verbs() const | ||
258 | { | ||
259 | return verb_query(*this); | ||
260 | } | ||
261 | 37 | ||
262 | adjective_query adjectives() const | 38 | ~data(); |
263 | { | ||
264 | return adjective_query(*this); | ||
265 | } | ||
266 | 39 | ||
267 | adverb_query adverbs() const | 40 | verb_query verbs() const; |
268 | { | 41 | adjective_query adjectives() const; |
269 | return adverb_query(*this); | 42 | adverb_query adverbs() const; |
270 | } | 43 | noun_query nouns() const; |
271 | 44 | ||
272 | }; | 45 | }; |
273 | 46 | ||
diff --git a/verbly/noun.cpp b/verbly/noun.cpp new file mode 100644 index 0000000..9336a1c --- /dev/null +++ b/verbly/noun.cpp | |||
@@ -0,0 +1,916 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | noun::noun(const data& _data, int _id) : word(_data, _id) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | std::string noun::base_form() const | ||
11 | { | ||
12 | return _singular; | ||
13 | } | ||
14 | |||
15 | std::string noun::singular_form() const | ||
16 | { | ||
17 | return _singular; | ||
18 | } | ||
19 | |||
20 | std::string noun::plural_form() const | ||
21 | { | ||
22 | return _plural; | ||
23 | } | ||
24 | |||
25 | bool noun::has_plural_form() const | ||
26 | { | ||
27 | return !_plural.empty(); | ||
28 | } | ||
29 | |||
30 | noun_query noun::hypernyms() const | ||
31 | { | ||
32 | return _data.nouns().hypernym_of(*this); | ||
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 | |||
204 | return *this; | ||
205 | } | ||
206 | |||
207 | noun_query& noun_query::not_part_meronym_of(const noun& _noun) | ||
208 | { | ||
209 | _not_part_meronym_of.push_back(_noun); | ||
210 | |||
211 | return *this; | ||
212 | } | ||
213 | |||
214 | noun_query& noun_query::is_part_holonym(bool _arg) | ||
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::instance_of(const noun& _noun) | ||
327 | { | ||
328 | _instance_of.push_back(_noun); | ||
329 | |||
330 | return *this; | ||
331 | } | ||
332 | |||
333 | noun_query& noun_query::not_instance_of(const noun& _noun) | ||
334 | { | ||
335 | _not_instance_of.push_back(_noun); | ||
336 | |||
337 | return *this; | ||
338 | } | ||
339 | |||
340 | noun_query& noun_query::is_class(bool _arg) | ||
341 | { | ||
342 | _is_class = _arg; | ||
343 | |||
344 | return *this; | ||
345 | } | ||
346 | |||
347 | noun_query& noun_query::class_of(const noun& _noun) | ||
348 | { | ||
349 | _class_of.push_back(_noun); | ||
350 | |||
351 | return *this; | ||
352 | } | ||
353 | |||
354 | noun_query& noun_query::not_class_of(const noun& _noun) | ||
355 | { | ||
356 | _not_class_of.push_back(_noun); | ||
357 | |||
358 | return *this; | ||
359 | } | ||
360 | |||
361 | noun_query& noun_query::has_synonyms(bool _arg) | ||
362 | { | ||
363 | _has_synonyms = _arg; | ||
364 | |||
365 | return *this; | ||
366 | } | ||
367 | |||
368 | noun_query& noun_query::synonym_of(const noun& _noun) | ||
369 | { | ||
370 | _synonym_of.push_back(_noun); | ||
371 | |||
372 | return *this; | ||
373 | } | ||
374 | |||
375 | noun_query& noun_query::not_synonym_of(const noun& _noun) | ||
376 | { | ||
377 | _not_synonym_of.push_back(_noun); | ||
378 | |||
379 | return *this; | ||
380 | } | ||
381 | |||
382 | noun_query& noun_query::has_antonyms(bool _arg) | ||
383 | { | ||
384 | _has_antonyms = _arg; | ||
385 | |||
386 | return *this; | ||
387 | } | ||
388 | |||
389 | noun_query& noun_query::antonym_of(const noun& _noun) | ||
390 | { | ||
391 | _antonym_of.push_back(_noun); | ||
392 | |||
393 | return *this; | ||
394 | } | ||
395 | |||
396 | noun_query& noun_query::not_antonym_of(const noun& _noun) | ||
397 | { | ||
398 | _not_antonym_of.push_back(_noun); | ||
399 | |||
400 | return *this; | ||
401 | } | ||
402 | |||
403 | noun_query& noun_query::has_pertainym(bool _arg) | ||
404 | { | ||
405 | _has_pertainym = _arg; | ||
406 | |||
407 | return *this; | ||
408 | } | ||
409 | |||
410 | noun_query& noun_query::anti_pertainym_of(const adjective& _adj) | ||
411 | { | ||
412 | _anti_pertainym_of.push_back(_adj); | ||
413 | |||
414 | return *this; | ||
415 | } | ||
416 | |||
417 | noun_query& noun_query::is_attribute(bool _arg) | ||
418 | { | ||
419 | _is_attribute = _arg; | ||
420 | |||
421 | return *this; | ||
422 | } | ||
423 | |||
424 | noun_query& noun_query::attribute_of(const adjective& _adj) | ||
425 | { | ||
426 | _attribute_of.push_back(_adj); | ||
427 | |||
428 | return *this; | ||
429 | } | ||
430 | |||
431 | std::list<noun> noun_query::run() const | ||
432 | { | ||
433 | std::stringstream construct; | ||
434 | construct << "SELECT noun_id, singular, plural FROM nouns"; | ||
435 | std::list<std::string> conditions; | ||
436 | |||
437 | if (_has_prn) | ||
438 | { | ||
439 | conditions.push_back("noun_id IN (SELECT noun_id FROM noun_pronunciations)"); | ||
440 | } | ||
441 | |||
442 | if (!_rhymes.empty()) | ||
443 | { | ||
444 | std::list<std::string> clauses(_rhymes.size(), "pronunciation LIKE @RHMPRN"); | ||
445 | std::string cond = "noun_id IN (SELECT noun_id FROM noun_pronunciations WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
446 | conditions.push_back(cond); | ||
447 | } | ||
448 | |||
449 | for (auto except : _except) | ||
450 | { | ||
451 | conditions.push_back("noun_id != @EXCID"); | ||
452 | } | ||
453 | |||
454 | if (_is_hypernym) | ||
455 | { | ||
456 | conditions.push_back("noun_id IN (SELECT hypernym_id FROM hypernymy)"); | ||
457 | } | ||
458 | |||
459 | if (!_hypernym_of.empty()) | ||
460 | { | ||
461 | std::list<std::string> clauses(_hypernym_of.size(), "hyponym_id = @HYPO"); | ||
462 | std::string cond = "noun_id IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
463 | conditions.push_back(cond); | ||
464 | } | ||
465 | |||
466 | if (!_not_hypernym_of.empty()) | ||
467 | { | ||
468 | std::list<std::string> clauses(_not_hypernym_of.size(), "hyponym_id = @NHYPO"); | ||
469 | std::string cond = "noun_id NOT IN (SELECT hypernym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
470 | conditions.push_back(cond); | ||
471 | } | ||
472 | |||
473 | if (_is_hyponym) | ||
474 | { | ||
475 | conditions.push_back("noun_id IN (SELECT hyponym_id FROM hypernymy)"); | ||
476 | } | ||
477 | |||
478 | if (!_hyponym_of.empty()) | ||
479 | { | ||
480 | std::list<std::string> clauses(_hyponym_of.size(), "hypernym_id = @HYPER"); | ||
481 | std::string cond = "noun_id IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
482 | conditions.push_back(cond); | ||
483 | } | ||
484 | |||
485 | if (!_not_hyponym_of.empty()) | ||
486 | { | ||
487 | std::list<std::string> clauses(_not_hyponym_of.size(), "hypernym_id = @NHYPER"); | ||
488 | std::string cond = "noun_id NOT IN (SELECT hyponym_id FROM hypernymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
489 | conditions.push_back(cond); | ||
490 | } | ||
491 | |||
492 | if (_is_part_meronym) | ||
493 | { | ||
494 | conditions.push_back("noun_id IN (SELECT meronym_id FROM part_meronymy)"); | ||
495 | } | ||
496 | |||
497 | if (!_part_meronym_of.empty()) | ||
498 | { | ||
499 | std::list<std::string> clauses(_part_meronym_of.size(), "holonym_id = @PHOLO"); | ||
500 | std::string cond = "noun_id IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
501 | conditions.push_back(cond); | ||
502 | } | ||
503 | |||
504 | if (!_not_part_meronym_of.empty()) | ||
505 | { | ||
506 | std::list<std::string> clauses(_not_part_meronym_of.size(), "holonym_id = @NPHOLO"); | ||
507 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
508 | conditions.push_back(cond); | ||
509 | } | ||
510 | |||
511 | if (_is_part_holonym) | ||
512 | { | ||
513 | conditions.push_back("noun_id IN (SELECT holonym_id FROM part_meronymy)"); | ||
514 | } | ||
515 | |||
516 | if (!_part_holonym_of.empty()) | ||
517 | { | ||
518 | std::list<std::string> clauses(_part_holonym_of.size(), "meronym_id = @PMERO"); | ||
519 | std::string cond = "noun_id IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
520 | conditions.push_back(cond); | ||
521 | } | ||
522 | |||
523 | if (!_not_part_holonym_of.empty()) | ||
524 | { | ||
525 | std::list<std::string> clauses(_not_part_holonym_of.size(), "meronym_id = @NPMERO"); | ||
526 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM part_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
527 | conditions.push_back(cond); | ||
528 | } | ||
529 | |||
530 | if (_is_substance_meronym) | ||
531 | { | ||
532 | conditions.push_back("noun_id IN (SELECT meronym_id FROM substance_meronymy)"); | ||
533 | } | ||
534 | |||
535 | if (!_substance_meronym_of.empty()) | ||
536 | { | ||
537 | std::list<std::string> clauses(_substance_meronym_of.size(), "holonym_id = @SHOLO"); | ||
538 | std::string cond = "noun_id IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
539 | conditions.push_back(cond); | ||
540 | } | ||
541 | |||
542 | if (!_not_substance_meronym_of.empty()) | ||
543 | { | ||
544 | std::list<std::string> clauses(_not_substance_meronym_of.size(), "holonym_id = @NSHOLO"); | ||
545 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
546 | conditions.push_back(cond); | ||
547 | } | ||
548 | |||
549 | if (_is_substance_holonym) | ||
550 | { | ||
551 | conditions.push_back("noun_id IN (SELECT holonym_id FROM substance_meronymy)"); | ||
552 | } | ||
553 | |||
554 | if (!_substance_holonym_of.empty()) | ||
555 | { | ||
556 | std::list<std::string> clauses(_substance_holonym_of.size(), "meronym_id = @SMERO"); | ||
557 | std::string cond = "noun_id IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
558 | conditions.push_back(cond); | ||
559 | } | ||
560 | |||
561 | if (!_not_substance_holonym_of.empty()) | ||
562 | { | ||
563 | std::list<std::string> clauses(_not_substance_holonym_of.size(), "meronym_id = @NSMERO"); | ||
564 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM substance_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
565 | conditions.push_back(cond); | ||
566 | } | ||
567 | |||
568 | if (_is_member_meronym) | ||
569 | { | ||
570 | conditions.push_back("noun_id IN (SELECT meronym_id FROM member_meronymy)"); | ||
571 | } | ||
572 | |||
573 | if (!_member_meronym_of.empty()) | ||
574 | { | ||
575 | std::list<std::string> clauses(_member_meronym_of.size(), "holonym_id = @MHOLO"); | ||
576 | std::string cond = "noun_id IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
577 | conditions.push_back(cond); | ||
578 | } | ||
579 | |||
580 | if (!_not_member_meronym_of.empty()) | ||
581 | { | ||
582 | std::list<std::string> clauses(_not_member_meronym_of.size(), "holonym_id = @NMHOLO"); | ||
583 | std::string cond = "noun_id NOT IN (SELECT meronym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
584 | conditions.push_back(cond); | ||
585 | } | ||
586 | |||
587 | if (_is_member_holonym) | ||
588 | { | ||
589 | conditions.push_back("noun_id IN (SELECT holonym_id FROM member_meronym)"); | ||
590 | } | ||
591 | |||
592 | if (!_member_holonym_of.empty()) | ||
593 | { | ||
594 | std::list<std::string> clauses(_member_holonym_of.size(), "meronym_id = @MMERO"); | ||
595 | std::string cond = "noun_id IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
596 | conditions.push_back(cond); | ||
597 | } | ||
598 | |||
599 | if (!_not_member_holonym_of.empty()) | ||
600 | { | ||
601 | std::list<std::string> clauses(_not_member_holonym_of.size(), "meronym_id = @NMMERO"); | ||
602 | std::string cond = "noun_id NOT IN (SELECT holonym_id FROM member_meronymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
603 | conditions.push_back(cond); | ||
604 | } | ||
605 | |||
606 | if (_is_proper) | ||
607 | { | ||
608 | conditions.push_back("noun_id IN (SELECT instance_id FROM instantiation)"); | ||
609 | } | ||
610 | |||
611 | if (!_instance_of.empty()) | ||
612 | { | ||
613 | std::list<std::string> clauses(_instance_of.size(), "class_id = @CLSID"); | ||
614 | std::string cond = "noun_id IN (SELECT instance_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
615 | conditions.push_back(cond); | ||
616 | } | ||
617 | |||
618 | if (!_not_instance_of.empty()) | ||
619 | { | ||
620 | std::list<std::string> clauses(_not_instance_of.size(), "class_id = @NCLSID"); | ||
621 | std::string cond = "noun_id NOT IN (SELECT instance_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
622 | conditions.push_back(cond); | ||
623 | } | ||
624 | |||
625 | if (_is_class) | ||
626 | { | ||
627 | conditions.push_back("noun_id IN (SELECT class_id FROM instantiation)"); | ||
628 | } | ||
629 | |||
630 | if (!_class_of.empty()) | ||
631 | { | ||
632 | std::list<std::string> clauses(_class_of.size(), "instance_id = @INSID"); | ||
633 | std::string cond = "noun_id IN (SELECT class_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
634 | conditions.push_back(cond); | ||
635 | } | ||
636 | |||
637 | if (!_not_class_of.empty()) | ||
638 | { | ||
639 | std::list<std::string> clauses(_not_class_of.size(), "instance_id = @NINSID"); | ||
640 | std::string cond = "noun_id NOT IN (SELECT class_id FROM instantiation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
641 | conditions.push_back(cond); | ||
642 | } | ||
643 | |||
644 | if (_has_synonyms) | ||
645 | { | ||
646 | conditions.push_back("noun_id IN (SELECT adjective_2_id FROM adjective_synonymy)"); | ||
647 | } | ||
648 | |||
649 | if (!_synonym_of.empty()) | ||
650 | { | ||
651 | std::list<std::string> clauses(_synonym_of.size(), "adjective_1_id = @SYNID"); | ||
652 | std::string cond = "noun_id IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
653 | conditions.push_back(cond); | ||
654 | } | ||
655 | |||
656 | if (!_not_synonym_of.empty()) | ||
657 | { | ||
658 | std::list<std::string> clauses(_not_synonym_of.size(), "adjective_1_id = @NSYNID"); | ||
659 | std::string cond = "noun_id NOT IN (SELECT adjective_2_id FROM adjective_synonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
660 | conditions.push_back(cond); | ||
661 | } | ||
662 | |||
663 | if (_has_antonyms) | ||
664 | { | ||
665 | conditions.push_back("noun_id IN (SELECT adjective_2_id FROM adjective_antonymy)"); | ||
666 | } | ||
667 | |||
668 | if (!_antonym_of.empty()) | ||
669 | { | ||
670 | std::list<std::string> clauses(_antonym_of.size(), "adjective_1_id = @ANTID"); | ||
671 | std::string cond = "noun_id IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
672 | conditions.push_back(cond); | ||
673 | } | ||
674 | |||
675 | if (!_not_antonym_of.empty()) | ||
676 | { | ||
677 | std::list<std::string> clauses(_not_antonym_of.size(), "adjective_1_id = @NANTID"); | ||
678 | std::string cond = "noun_id NOT IN (SELECT adjective_2_id FROM adjective_antonymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
679 | conditions.push_back(cond); | ||
680 | } | ||
681 | |||
682 | if (_has_pertainym) | ||
683 | { | ||
684 | conditions.push_back("noun_id IN (SELECT noun_id FROM pertainymy)"); | ||
685 | } | ||
686 | |||
687 | if (!_anti_pertainym_of.empty()) | ||
688 | { | ||
689 | std::list<std::string> clauses(_anti_pertainym_of.size(), "pertainym_id = @PERID"); | ||
690 | std::string cond = "noun_id IN (SELECT noun_id FROM pertainymy WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
691 | conditions.push_back(cond); | ||
692 | } | ||
693 | |||
694 | if (_is_attribute) | ||
695 | { | ||
696 | conditions.push_back("noun_id IN (SELECT noun_id FROM variation)"); | ||
697 | } | ||
698 | |||
699 | if (!_attribute_of.empty()) | ||
700 | { | ||
701 | std::list<std::string> clauses(_attribute_of.size(), "adjective_id = @VALID"); | ||
702 | std::string cond = "noun_id IN (SELECT noun_id FROM variation WHERE " + verbly::implode(std::begin(clauses), std::end(clauses), " OR ") + ")"; | ||
703 | conditions.push_back(cond); | ||
704 | } | ||
705 | |||
706 | if (!conditions.empty()) | ||
707 | { | ||
708 | construct << " WHERE "; | ||
709 | construct << verbly::implode(std::begin(conditions), std::end(conditions), " AND "); | ||
710 | } | ||
711 | |||
712 | if (_random) | ||
713 | { | ||
714 | construct << " ORDER BY RANDOM()"; | ||
715 | } | ||
716 | |||
717 | if (_limit != unlimited) | ||
718 | { | ||
719 | construct << " LIMIT " << _limit; | ||
720 | } | ||
721 | |||
722 | sqlite3_stmt* ppstmt; | ||
723 | std::string query = construct.str(); | ||
724 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
725 | { | ||
726 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
727 | } | ||
728 | |||
729 | if (!_rhymes.empty()) | ||
730 | { | ||
731 | int i = 0; | ||
732 | for (auto rhyme : _rhymes) | ||
733 | { | ||
734 | std::string rhymer = "%" + rhyme; | ||
735 | sqlite3_bind_text(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@RHMPRN"), rhymer.c_str(), rhymer.length(), SQLITE_STATIC); | ||
736 | |||
737 | i++; | ||
738 | } | ||
739 | } | ||
740 | |||
741 | for (auto except : _except) | ||
742 | { | ||
743 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@EXCID"), except._id); | ||
744 | } | ||
745 | |||
746 | for (auto hyponym : _hypernym_of) | ||
747 | { | ||
748 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPO"), hyponym._id); | ||
749 | } | ||
750 | |||
751 | for (auto hyponym : _not_hypernym_of) | ||
752 | { | ||
753 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NHYPO"), hyponym._id); | ||
754 | } | ||
755 | |||
756 | for (auto hypernym : _hyponym_of) | ||
757 | { | ||
758 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@HYPER"), hypernym._id); | ||
759 | } | ||
760 | |||
761 | for (auto hypernym : _not_hyponym_of) | ||
762 | { | ||
763 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NHYPER"), hypernym._id); | ||
764 | } | ||
765 | |||
766 | for (auto holonym : _part_meronym_of) | ||
767 | { | ||
768 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PHOLO"), holonym._id); | ||
769 | } | ||
770 | |||
771 | for (auto holonym : _not_part_meronym_of) | ||
772 | { | ||
773 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NPHOLO"), holonym._id); | ||
774 | } | ||
775 | |||
776 | for (auto meronym : _part_holonym_of) | ||
777 | { | ||
778 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PMERO"), meronym._id); | ||
779 | } | ||
780 | |||
781 | for (auto meronym : _not_part_holonym_of) | ||
782 | { | ||
783 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NPMERO"), meronym._id); | ||
784 | } | ||
785 | |||
786 | for (auto holonym : _substance_meronym_of) | ||
787 | { | ||
788 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SHOLO"), holonym._id); | ||
789 | } | ||
790 | |||
791 | for (auto holonym : _not_substance_meronym_of) | ||
792 | { | ||
793 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSHOLO"), holonym._id); | ||
794 | } | ||
795 | |||
796 | for (auto meronym : _substance_holonym_of) | ||
797 | { | ||
798 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SMERO"), meronym._id); | ||
799 | } | ||
800 | |||
801 | for (auto meronym : _not_substance_holonym_of) | ||
802 | { | ||
803 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSMERO"), meronym._id); | ||
804 | } | ||
805 | |||
806 | for (auto holonym : _member_meronym_of) | ||
807 | { | ||
808 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MHOLO"), holonym._id); | ||
809 | } | ||
810 | |||
811 | for (auto holonym : _not_member_meronym_of) | ||
812 | { | ||
813 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NMHOLO"), holonym._id); | ||
814 | } | ||
815 | |||
816 | for (auto meronym : _member_holonym_of) | ||
817 | { | ||
818 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@MMERO"), meronym._id); | ||
819 | } | ||
820 | |||
821 | for (auto meronym : _not_member_holonym_of) | ||
822 | { | ||
823 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NMMERO"), meronym._id); | ||
824 | } | ||
825 | |||
826 | for (auto cls : _instance_of) | ||
827 | { | ||
828 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@CLSID"), cls._id); | ||
829 | } | ||
830 | |||
831 | for (auto cls : _not_instance_of) | ||
832 | { | ||
833 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NCLSID"), cls._id); | ||
834 | } | ||
835 | |||
836 | for (auto inst : _class_of) | ||
837 | { | ||
838 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@INSID"), inst._id); | ||
839 | } | ||
840 | |||
841 | for (auto inst : _not_class_of) | ||
842 | { | ||
843 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NINSID"), inst._id); | ||
844 | } | ||
845 | |||
846 | for (auto synonym : _synonym_of) | ||
847 | { | ||
848 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@SYNID"), synonym._id); | ||
849 | } | ||
850 | |||
851 | for (auto synonym : _not_synonym_of) | ||
852 | { | ||
853 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NSYNID"), synonym._id); | ||
854 | } | ||
855 | |||
856 | for (auto antonym : _antonym_of) | ||
857 | { | ||
858 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@ANTID"), antonym._id); | ||
859 | } | ||
860 | |||
861 | for (auto antonym : _not_antonym_of) | ||
862 | { | ||
863 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@NANTID"), antonym._id); | ||
864 | } | ||
865 | |||
866 | for (auto pertainym : _anti_pertainym_of) | ||
867 | { | ||
868 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@PERID"), pertainym._id); | ||
869 | } | ||
870 | |||
871 | for (auto value : _attribute_of) | ||
872 | { | ||
873 | sqlite3_bind_int(ppstmt, sqlite3_bind_parameter_index(ppstmt, "@VALID"), value._id); | ||
874 | } | ||
875 | |||
876 | std::list<noun> output; | ||
877 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
878 | { | ||
879 | noun tnc {_data, sqlite3_column_int(ppstmt, 0)}; | ||
880 | tnc._singular = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); | ||
881 | |||
882 | if (sqlite3_column_type(ppstmt, 2) != SQLITE_NULL) | ||
883 | { | ||
884 | tnc._plural = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 2))); | ||
885 | } | ||
886 | |||
887 | output.push_back(tnc); | ||
888 | } | ||
889 | |||
890 | sqlite3_finalize(ppstmt); | ||
891 | |||
892 | for (auto& noun : output) | ||
893 | { | ||
894 | query = "SELECT pronunciation FROM noun_pronunciations WHERE noun_id = ?"; | ||
895 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
896 | { | ||
897 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
898 | } | ||
899 | |||
900 | sqlite3_bind_int(ppstmt, 1, noun._id); | ||
901 | |||
902 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
903 | { | ||
904 | std::string pronunciation(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 0))); | ||
905 | auto phonemes = verbly::split<std::list<std::string>>(pronunciation, " "); | ||
906 | |||
907 | noun.pronunciations.push_back(phonemes); | ||
908 | } | ||
909 | |||
910 | sqlite3_finalize(ppstmt); | ||
911 | } | ||
912 | |||
913 | return output; | ||
914 | } | ||
915 | |||
916 | }; | ||
diff --git a/verbly/noun.h b/verbly/noun.h new file mode 100644 index 0000000..f5ba256 --- /dev/null +++ b/verbly/noun.h | |||
@@ -0,0 +1,171 @@ | |||
1 | #ifndef NOUN_H_24A03C83 | ||
2 | #define NOUN_H_24A03C83 | ||
3 | |||
4 | namespace verbly { | ||
5 | |||
6 | class noun : public word { | ||
7 | private: | ||
8 | std::string _singular; | ||
9 | std::string _plural; | ||
10 | |||
11 | friend class noun_query; | ||
12 | |||
13 | public: | ||
14 | noun(const data& _data, int _id); | ||
15 | |||
16 | std::string base_form() const; | ||
17 | std::string singular_form() const; | ||
18 | std::string plural_form() const; | ||
19 | |||
20 | bool has_plural_form() const; | ||
21 | |||
22 | noun_query hypernyms() const; | ||
23 | noun_query hyponyms() const; | ||
24 | noun_query part_meronyms() const; | ||
25 | noun_query part_holonyms() const; | ||
26 | noun_query substance_meronyms() const; | ||
27 | noun_query substance_holonyms() const; | ||
28 | noun_query member_meronyms() const; | ||
29 | noun_query member_holonyms() const; | ||
30 | noun_query classes() const; | ||
31 | noun_query instances() const; | ||
32 | noun_query synonyms() const; | ||
33 | noun_query antonyms() const; | ||
34 | adjective_query pertainyms() const; | ||
35 | 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& instance_of(const noun& _noun); | ||
82 | noun_query& not_instance_of(const noun& _noun); | ||
83 | |||
84 | noun_query& is_class(bool _arg); | ||
85 | noun_query& class_of(const noun& _noun); | ||
86 | noun_query& not_class_of(const noun& _noun); | ||
87 | |||
88 | noun_query& has_synonyms(bool _arg); | ||
89 | noun_query& synonym_of(const noun& _noun); | ||
90 | noun_query& not_synonym_of(const noun& _noun); | ||
91 | |||
92 | noun_query& has_antonyms(bool _arg); | ||
93 | noun_query& antonym_of(const noun& _noun); | ||
94 | noun_query& not_antonym_of(const noun& _noun); | ||
95 | |||
96 | noun_query& has_pertainym(bool _arg); | ||
97 | noun_query& anti_pertainym_of(const adjective& _adj); | ||
98 | |||
99 | noun_query& is_attribute(bool _arg); | ||
100 | noun_query& attribute_of(const adjective& _adj); | ||
101 | |||
102 | std::list<noun> run() const; | ||
103 | |||
104 | const static int unlimited = -1; | ||
105 | |||
106 | private: | ||
107 | const data& _data; | ||
108 | int _limit = unlimited; | ||
109 | bool _random = false; | ||
110 | std::list<std::string> _rhymes; | ||
111 | std::list<noun> _except; | ||
112 | bool _has_prn = false; | ||
113 | |||
114 | bool _is_hypernym = false; | ||
115 | std::list<noun> _hypernym_of; | ||
116 | std::list<noun> _not_hypernym_of; | ||
117 | |||
118 | bool _is_hyponym = false; | ||
119 | std::list<noun> _hyponym_of; | ||
120 | std::list<noun> _not_hyponym_of; | ||
121 | |||
122 | bool _is_part_meronym = false; | ||
123 | std::list<noun> _part_meronym_of; | ||
124 | std::list<noun> _not_part_meronym_of; | ||
125 | |||
126 | bool _is_substance_meronym = false; | ||
127 | std::list<noun> _substance_meronym_of; | ||
128 | std::list<noun> _not_substance_meronym_of; | ||
129 | |||
130 | bool _is_member_meronym = false; | ||
131 | std::list<noun> _member_meronym_of; | ||
132 | std::list<noun> _not_member_meronym_of; | ||
133 | |||
134 | bool _is_part_holonym = false; | ||
135 | std::list<noun> _part_holonym_of; | ||
136 | std::list<noun> _not_part_holonym_of; | ||
137 | |||
138 | bool _is_substance_holonym = false; | ||
139 | std::list<noun> _substance_holonym_of; | ||
140 | std::list<noun> _not_substance_holonym_of; | ||
141 | |||
142 | bool _is_member_holonym = false; | ||
143 | std::list<noun> _member_holonym_of; | ||
144 | std::list<noun> _not_member_holonym_of; | ||
145 | |||
146 | bool _is_proper = false; | ||
147 | std::list<noun> _instance_of; | ||
148 | std::list<noun> _not_instance_of; | ||
149 | |||
150 | bool _is_class = false; | ||
151 | std::list<noun> _class_of; | ||
152 | std::list<noun> _not_class_of; | ||
153 | |||
154 | bool _has_synonyms = false; | ||
155 | std::list<noun> _synonym_of; | ||
156 | std::list<noun> _not_synonym_of; | ||
157 | |||
158 | bool _has_antonyms = false; | ||
159 | std::list<noun> _antonym_of; | ||
160 | std::list<noun> _not_antonym_of; | ||
161 | |||
162 | bool _has_pertainym = false; | ||
163 | std::list<adjective> _anti_pertainym_of; | ||
164 | |||
165 | bool _is_attribute = false; | ||
166 | std::list<adjective> _attribute_of; | ||
167 | }; | ||
168 | |||
169 | }; | ||
170 | |||
171 | #endif /* end of include guard: NOUN_H_24A03C83 */ | ||
diff --git a/verbly/token.cpp b/verbly/token.cpp new file mode 100644 index 0000000..aa8f50e --- /dev/null +++ b/verbly/token.cpp | |||
@@ -0,0 +1,53 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | token::token(token::type _type) : _type(_type) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | token::type token::token_type() const | ||
11 | { | ||
12 | return _type; | ||
13 | } | ||
14 | |||
15 | verb_token::verb_token(const class verb& _verb) : token(token::type::verb), _verb(&_verb) | ||
16 | { | ||
17 | |||
18 | } | ||
19 | |||
20 | const class verb& verb_token::verb() const | ||
21 | { | ||
22 | return *_verb; | ||
23 | } | ||
24 | |||
25 | verb_token& verb_token::inflect(verb_token::inflection infl) | ||
26 | { | ||
27 | _inflection = infl; | ||
28 | return *this; | ||
29 | } | ||
30 | |||
31 | bool verb_token::complete() const | ||
32 | { | ||
33 | return true; | ||
34 | } | ||
35 | |||
36 | std::string verb_token::compile() const | ||
37 | { | ||
38 | switch (_inflection) | ||
39 | { | ||
40 | case inflection::infinitive: return _verb->infinitive_form(); | ||
41 | case inflection::past_tense: return _verb->past_tense_form(); | ||
42 | case inflection::past_participle: return _verb->past_participle_form(); | ||
43 | case inflection::ing_form: return _verb->ing_form(); | ||
44 | case inflection::s_form: return _verb->s_form(); | ||
45 | } | ||
46 | } | ||
47 | |||
48 | token* verb_token::copy() const | ||
49 | { | ||
50 | return new verb_token(*this); | ||
51 | } | ||
52 | |||
53 | }; | ||
diff --git a/verbly/token.h b/verbly/token.h index 2848fd0..44d99cb 100644 --- a/verbly/token.h +++ b/verbly/token.h | |||
@@ -4,16 +4,10 @@ | |||
4 | #include <string> | 4 | #include <string> |
5 | #include <list> | 5 | #include <list> |
6 | #include <sstream> | 6 | #include <sstream> |
7 | #include "verb.h" | ||
8 | 7 | ||
9 | namespace verbly { | 8 | namespace verbly { |
10 | 9 | ||
11 | enum class type { | 10 | class verb; |
12 | verb, | ||
13 | fillin, | ||
14 | string, | ||
15 | utterance | ||
16 | }; | ||
17 | 11 | ||
18 | class selrestr { | 12 | class selrestr { |
19 | }; | 13 | }; |
@@ -29,20 +23,22 @@ namespace verbly { | |||
29 | }; | 23 | }; |
30 | 24 | ||
31 | class token { | 25 | class token { |
26 | public: | ||
27 | enum class type { | ||
28 | verb, | ||
29 | fillin, | ||
30 | string, | ||
31 | utterance | ||
32 | }; | ||
33 | |||
32 | protected: | 34 | protected: |
33 | // General | 35 | // General |
34 | type type; | 36 | type _type; |
35 | 37 | ||
36 | token(enum type type) : type(type) | 38 | token(type _type); |
37 | { | ||
38 | |||
39 | } | ||
40 | 39 | ||
41 | public: | 40 | public: |
42 | enum type token_type() const | 41 | enum type token_type() const; |
43 | { | ||
44 | return type; | ||
45 | } | ||
46 | 42 | ||
47 | virtual bool complete() const = 0; | 43 | virtual bool complete() const = 0; |
48 | virtual std::string compile() const = 0; | 44 | virtual std::string compile() const = 0; |
@@ -50,42 +46,32 @@ namespace verbly { | |||
50 | }; | 46 | }; |
51 | 47 | ||
52 | class verb_token : public token { | 48 | class verb_token : public token { |
49 | public: | ||
50 | enum class inflection { | ||
51 | infinitive, | ||
52 | past_tense, | ||
53 | past_participle, | ||
54 | ing_form, | ||
55 | s_form | ||
56 | }; | ||
57 | |||
53 | private: | 58 | private: |
54 | // Verb | 59 | // Verb |
55 | const verb* m_verb; | 60 | const verb* _verb; |
56 | conjugation verb_infl = conjugation::infinitive; | 61 | inflection _inflection = inflection::infinitive; |
57 | 62 | ||
58 | public: | 63 | public: |
59 | verb_token(const class verb& verb) : token(type::verb), m_verb(&verb) | 64 | verb_token(const class verb& _verb); |
60 | { | ||
61 | |||
62 | } | ||
63 | 65 | ||
64 | const class verb& verb() const | 66 | const class verb& verb() const; |
65 | { | ||
66 | return *m_verb; | ||
67 | } | ||
68 | 67 | ||
69 | verb_token& conjugate(conjugation infl) | 68 | verb_token& inflect(inflection infl); |
70 | { | ||
71 | verb_infl = infl; | ||
72 | return *this; | ||
73 | } | ||
74 | 69 | ||
75 | bool complete() const | 70 | bool complete() const; |
76 | { | ||
77 | return true; | ||
78 | } | ||
79 | 71 | ||
80 | std::string compile() const | 72 | std::string compile() const; |
81 | { | ||
82 | return m_verb->conjugate(verb_infl); | ||
83 | } | ||
84 | 73 | ||
85 | token* copy() const | 74 | token* copy() const; |
86 | { | ||
87 | return new verb_token(*this); | ||
88 | } | ||
89 | }; | 75 | }; |
90 | 76 | ||
91 | class utterance_token : public token { | 77 | class utterance_token : public token { |
@@ -140,7 +126,7 @@ namespace verbly { | |||
140 | } | 126 | } |
141 | };*/ | 127 | };*/ |
142 | 128 | ||
143 | utterance_token(std::initializer_list<token*> tkns) : token(type::utterance) | 129 | utterance_token(std::initializer_list<token*> tkns) : token(token::type::utterance) |
144 | { | 130 | { |
145 | for (auto tkn : tkns) | 131 | for (auto tkn : tkns) |
146 | { | 132 | { |
@@ -148,7 +134,7 @@ namespace verbly { | |||
148 | } | 134 | } |
149 | } | 135 | } |
150 | 136 | ||
151 | utterance_token(const utterance_token& other) : token(type::utterance) | 137 | utterance_token(const utterance_token& other) : token(token::type::utterance) |
152 | { | 138 | { |
153 | for (auto& tkn : other.utterance) | 139 | for (auto& tkn : other.utterance) |
154 | { | 140 | { |
@@ -156,7 +142,7 @@ namespace verbly { | |||
156 | } | 142 | } |
157 | } | 143 | } |
158 | 144 | ||
159 | utterance_token(utterance_token&& other) : token(type::utterance), utterance(std::move(other.utterance)) | 145 | utterance_token(utterance_token&& other) : token(token::type::utterance), utterance(std::move(other.utterance)) |
160 | { | 146 | { |
161 | 147 | ||
162 | } | 148 | } |
@@ -237,7 +223,7 @@ namespace verbly { | |||
237 | fillin_type m_fillin_type; | 223 | fillin_type m_fillin_type; |
238 | 224 | ||
239 | public: | 225 | public: |
240 | fillin_token(fillin_type ft) : token(type::fillin), m_fillin_type(ft) | 226 | fillin_token(fillin_type ft) : token(token::type::fillin), m_fillin_type(ft) |
241 | { | 227 | { |
242 | 228 | ||
243 | } | 229 | } |
@@ -301,7 +287,7 @@ namespace verbly { | |||
301 | std::string str; | 287 | std::string str; |
302 | 288 | ||
303 | public: | 289 | public: |
304 | string_token(std::string str) : token(type::string), str(str) | 290 | string_token(std::string str) : token(token::type::string), str(str) |
305 | { | 291 | { |
306 | 292 | ||
307 | } | 293 | } |
diff --git a/verbly/util.h b/verbly/util.h new file mode 100644 index 0000000..815b47c --- /dev/null +++ b/verbly/util.h | |||
@@ -0,0 +1,53 @@ | |||
1 | #ifndef UTIL_H_15DDCA2D | ||
2 | #define UTIL_H_15DDCA2D | ||
3 | |||
4 | #include <string> | ||
5 | #include <iterator> | ||
6 | #include <sstream> | ||
7 | |||
8 | namespace verbly { | ||
9 | |||
10 | template <class InputIterator> | ||
11 | std::string implode(InputIterator first, InputIterator last, std::string delimiter) | ||
12 | { | ||
13 | std::stringstream result; | ||
14 | |||
15 | for (InputIterator it = first; it != last; it++) | ||
16 | { | ||
17 | if (it != first) | ||
18 | { | ||
19 | result << delimiter; | ||
20 | } | ||
21 | |||
22 | result << *it; | ||
23 | } | ||
24 | |||
25 | return result.str(); | ||
26 | } | ||
27 | |||
28 | template <class Container> | ||
29 | Container split(std::string input, std::string delimiter) | ||
30 | { | ||
31 | Container result; | ||
32 | |||
33 | while (!input.empty()) | ||
34 | { | ||
35 | int divider = input.find(" "); | ||
36 | if (divider == std::string::npos) | ||
37 | { | ||
38 | result.push_back(input); | ||
39 | |||
40 | input = ""; | ||
41 | } else { | ||
42 | result.push_back(input.substr(0, divider)); | ||
43 | |||
44 | input = input.substr(divider+1); | ||
45 | } | ||
46 | } | ||
47 | |||
48 | return result; | ||
49 | } | ||
50 | |||
51 | }; | ||
52 | |||
53 | #endif /* end of include guard: UTIL_H_15DDCA2D */ | ||
diff --git a/verbly/verb.cpp b/verbly/verb.cpp new file mode 100644 index 0000000..23f7c92 --- /dev/null +++ b/verbly/verb.cpp | |||
@@ -0,0 +1,193 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | verb::verb(const data& _data, int _id) : word(_data, _id) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | std::string verb::base_form() const | ||
11 | { | ||
12 | return _infinitive; | ||
13 | } | ||
14 | |||
15 | std::string verb::infinitive_form() const | ||
16 | { | ||
17 | return _infinitive; | ||
18 | } | ||
19 | |||
20 | std::string verb::past_tense_form() const | ||
21 | { | ||
22 | return _past_tense; | ||
23 | } | ||
24 | |||
25 | std::string verb::past_participle_form() const | ||
26 | { | ||
27 | return _past_participle; | ||
28 | } | ||
29 | |||
30 | std::string verb::ing_form() const | ||
31 | { | ||
32 | return _ing_form; | ||
33 | } | ||
34 | |||
35 | std::string verb::s_form() const | ||
36 | { | ||
37 | return _s_form; | ||
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 | |||
81 | return *this; | ||
82 | } | ||
83 | |||
84 | verb_query& verb_query::has_pronunciation(bool _has_prn) | ||
85 | { | ||
86 | this->_has_prn = _has_prn; | ||
87 | |||
88 | return *this; | ||
89 | } | ||
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 | |||
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 | }; | ||
diff --git a/verbly/verb.h b/verbly/verb.h index 42c8dc2..7cc87e2 100644 --- a/verbly/verb.h +++ b/verbly/verb.h | |||
@@ -1,8 +1,6 @@ | |||
1 | #ifndef VERB_H_BCC929AD | 1 | #ifndef VERB_H_BCC929AD |
2 | #define VERB_H_BCC929AD | 2 | #define VERB_H_BCC929AD |
3 | 3 | ||
4 | #include <vector> | ||
5 | |||
6 | namespace verbly { | 4 | namespace verbly { |
7 | 5 | ||
8 | /*class frame_part { | 6 | /*class frame_part { |
@@ -26,42 +24,50 @@ namespace verbly { | |||
26 | } | 24 | } |
27 | };*/ | 25 | };*/ |
28 | 26 | ||
29 | enum class conjugation { | 27 | class verb : public word { |
30 | present_participle, | ||
31 | past_participle, | ||
32 | infinitive | ||
33 | }; | ||
34 | |||
35 | class verb { | ||
36 | private: | 28 | private: |
37 | int id; | 29 | std::string _infinitive; |
30 | std::string _past_tense; | ||
31 | std::string _past_participle; | ||
32 | std::string _ing_form; | ||
33 | std::string _s_form; | ||
34 | |||
35 | friend class verb_query; | ||
38 | 36 | ||
39 | public: | 37 | public: |
40 | verb(int id) : id(id) | 38 | verb(const data& _data, int _id); |
41 | { | ||
42 | |||
43 | } | ||
44 | 39 | ||
45 | std::string infinitive; | 40 | std::string base_form() const; |
46 | std::string past_tense; | 41 | std::string infinitive_form() const; |
47 | std::string past_participle; | 42 | std::string past_tense_form() const; |
48 | std::string ing_form; | 43 | std::string past_participle_form() const; |
49 | std::string s_form; | 44 | std::string ing_form() const; |
50 | //std::vector<frame> frames; | 45 | std::string s_form() const; |
46 | }; | ||
47 | |||
48 | class verb_query { | ||
49 | public: | ||
50 | verb_query(const data& _data); | ||
51 | 51 | ||
52 | std::string conjugate(conjugation infl) const | 52 | verb_query& limit(int _limit); |
53 | { | 53 | verb_query& random(bool _random); |
54 | switch (infl) | 54 | verb_query& except(const verb& _word); |
55 | { | 55 | verb_query& rhymes_with(const word& _word); |
56 | case conjugation::infinitive: return infinitive; | 56 | verb_query& has_pronunciation(bool _has_prn); |
57 | case conjugation::past_participle: return past_participle; | 57 | |
58 | case conjugation::present_participle: return ing_form; | 58 | std::list<verb> run() const; |
59 | } | 59 | |
60 | } | 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; | ||
61 | }; | 69 | }; |
62 | 70 | ||
63 | }; | 71 | }; |
64 | 72 | ||
65 | #include "token.h" | ||
66 | |||
67 | #endif /* end of include guard: VERB_H_BCC929AD */ | 73 | #endif /* end of include guard: VERB_H_BCC929AD */ |
diff --git a/verbly/verbly.h b/verbly/verbly.h index 44fd3a8..b9f5367 100644 --- a/verbly/verbly.h +++ b/verbly/verbly.h | |||
@@ -2,10 +2,13 @@ | |||
2 | #define VERBLY_H_5B39CE50 | 2 | #define VERBLY_H_5B39CE50 |
3 | 3 | ||
4 | #include "c++14.h" | 4 | #include "c++14.h" |
5 | #include "util.h" | ||
5 | #include "token.h" | 6 | #include "token.h" |
7 | #include "data.h" | ||
8 | #include "word.h" | ||
6 | #include "verb.h" | 9 | #include "verb.h" |
7 | #include "adjective.h" | ||
8 | #include "adverb.h" | 10 | #include "adverb.h" |
9 | #include "data.h" | 11 | #include "adjective.h" |
12 | #include "noun.h" | ||
10 | 13 | ||
11 | #endif /* end of include guard: VERBLY_H_5B39CE50 */ | 14 | #endif /* end of include guard: VERBLY_H_5B39CE50 */ |
diff --git a/verbly/word.cpp b/verbly/word.cpp new file mode 100644 index 0000000..c50e7d3 --- /dev/null +++ b/verbly/word.cpp | |||
@@ -0,0 +1,32 @@ | |||
1 | #include "verbly.h" | ||
2 | |||
3 | namespace verbly { | ||
4 | |||
5 | word::word(const data& _data, int _id) : _data(_data), _id(_id) | ||
6 | { | ||
7 | |||
8 | } | ||
9 | |||
10 | std::list<std::string> word::rhyme_phonemes() const | ||
11 | { | ||
12 | std::list<std::string> result; | ||
13 | |||
14 | for (auto pronunciation : pronunciations) | ||
15 | { | ||
16 | auto phemstrt = std::find_if(std::begin(pronunciation), std::end(pronunciation), [] (std::string phoneme) { | ||
17 | return phoneme.find("1") != std::string::npos; | ||
18 | }); | ||
19 | |||
20 | std::stringstream rhymer; | ||
21 | for (auto it = phemstrt; it != std::end(pronunciation); it++) | ||
22 | { | ||
23 | rhymer << " " << *it; | ||
24 | } | ||
25 | |||
26 | result.push_back(rhymer.str()); | ||
27 | } | ||
28 | |||
29 | return result; | ||
30 | } | ||
31 | |||
32 | }; | ||
diff --git a/verbly/word.h b/verbly/word.h new file mode 100644 index 0000000..23ddb2b --- /dev/null +++ b/verbly/word.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #ifndef WORD_H_8FC89498 | ||
2 | #define WORD_H_8FC89498 | ||
3 | |||
4 | namespace verbly { | ||
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 { | ||
14 | protected: | ||
15 | const data& _data; | ||
16 | int _id; | ||
17 | |||
18 | std::list<std::list<std::string>> pronunciations; | ||
19 | |||
20 | word(const data& _data, int _id); | ||
21 | |||
22 | friend class adjective_query; | ||
23 | friend class verb_query; | ||
24 | friend class noun_query; | ||
25 | friend class adverb_query; | ||
26 | |||
27 | public: | ||
28 | virtual std::string base_form() const = 0; | ||
29 | |||
30 | std::list<std::string> rhyme_phonemes() const; | ||
31 | }; | ||
32 | |||
33 | }; | ||
34 | |||
35 | #endif /* end of include guard: WORD_H_8FC89498 */ | ||