about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore11
-rw-r--r--CMakeLists.txt8
-rw-r--r--furries.cpp15
-rw-r--r--generator.cpp451
-rw-r--r--schema.sql121
-rw-r--r--verbly/adjective.h2
-rw-r--r--verbly/adverb.h21
-rw-r--r--verbly/data.h79
-rw-r--r--verbly/token.h21
-rw-r--r--verbly/verbly.h1
10 files changed, 707 insertions, 23 deletions
diff --git a/.gitignore b/.gitignore index e9abc7f..461a080 100644 --- a/.gitignore +++ b/.gitignore
@@ -1 +1,10 @@
1config.yml \ No newline at end of file 1config.yml
2.DS_Store
3CMakeCache.txt
4CMakeFiles/
5Makefile
6cmake_install.cmake
7furries
8furries.dSYM/
9generator
10generator.dSYM/
diff --git a/CMakeLists.txt b/CMakeLists.txt index 054c972..0b6d991 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -6,9 +6,15 @@ add_subdirectory(vendor/twitcurl/libtwitcurl)
6find_package(PkgConfig) 6find_package(PkgConfig)
7pkg_check_modules(YamlCpp yaml-cpp REQUIRED) 7pkg_check_modules(YamlCpp yaml-cpp REQUIRED)
8pkg_check_modules(sqlite3 sqlite3 REQUIRED) 8pkg_check_modules(sqlite3 sqlite3 REQUIRED)
9find_package(libxml2 REQUIRED)
9 10
10include_directories(vendor/twitcurl/libtwitcurl ${sqlite3_INCLUDE_DIR}) 11include_directories(vendor/twitcurl/libtwitcurl ${LIBXML2_INCLUDE_DIR} ${sqlite3_INCLUDE_DIR})
11add_executable(furries furries.cpp) 12add_executable(furries furries.cpp)
12set_property(TARGET furries PROPERTY CXX_STANDARD 11) 13set_property(TARGET furries PROPERTY CXX_STANDARD 11)
13set_property(TARGET furries PROPERTY CXX_STANDARD_REQUIRED ON) 14set_property(TARGET furries PROPERTY CXX_STANDARD_REQUIRED ON)
14target_link_libraries(furries ${sqlite3_LIBRARIES} ${YamlCpp_LIBRARIES} twitcurl curl) 15target_link_libraries(furries ${sqlite3_LIBRARIES} ${YamlCpp_LIBRARIES} twitcurl curl)
16
17add_executable(generator generator.cpp)
18set_property(TARGET generator PROPERTY CXX_STANDARD 11)
19set_property(TARGET generator PROPERTY CXX_STANDARD_REQUIRED ON)
20target_link_libraries(generator ${sqlite3_LIBRARIES} ${LIBXML2_LIBRARIES})
diff --git a/furries.cpp b/furries.cpp index 2d0fb23..0cce8bd 100644 --- a/furries.cpp +++ b/furries.cpp
@@ -62,7 +62,15 @@ class fill_blanks {
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 const verbly::adjective& adj = database.adjectives().random(true).limit(1).run().front();
65 it = std::make_unique<verbly::string_token>(adj.value); 65 it = std::make_unique<verbly::string_token>(adj.form);
66
67 break;
68 }
69
70 case verbly::fillin_type::adverb:
71 {
72 const verbly::adverb& adv = database.adverbs().random(true).limit(1).run().front();
73 it = std::make_unique<verbly::string_token>(adv.form);
66 74
67 break; 75 break;
68 } 76 }
@@ -110,6 +118,11 @@ int main(int argc, char** argv)
110 new verbly::string_token("the furries are"), 118 new verbly::string_token("the furries are"),
111 new verbly::fillin_token(verbly::fillin_type::adjective) 119 new verbly::fillin_token(verbly::fillin_type::adjective)
112 }); 120 });
121 forms.push_back({
122 new verbly::string_token("the furries are"),
123 new verbly::fillin_token(verbly::fillin_type::adverb),
124 new verbly::fillin_token(verbly::fillin_type::adjective)
125 });
113 126
114 verbly::data database {"data.sqlite3"}; 127 verbly::data database {"data.sqlite3"};
115 fill_blanks yeah {database}; 128 fill_blanks yeah {database};
diff --git a/generator.cpp b/generator.cpp new file mode 100644 index 0000000..c389963 --- /dev/null +++ b/generator.cpp
@@ -0,0 +1,451 @@
1#include <libxml/parser.h>
2#include <iostream>
3#include <dirent.h>
4#include <set>
5#include <map>
6#include <string>
7#include <vector>
8#include <fstream>
9#include <sqlite3.h>
10#include <sstream>
11#include <regex>
12
13struct verb {
14 std::string infinitive;
15 std::string past_tense;
16 std::string past_participle;
17 std::string ing_form;
18 std::string s_form;
19};
20
21struct group {
22 std::string id;
23 std::set<std::string> members;
24};
25
26std::map<std::string, group> groups;
27std::map<std::string, verb> verbs;
28std::map<int, std::map<int, int>> wn;
29
30void print_usage()
31{
32 std::cout << "Verbly Datafile Generator" << std::endl;
33 std::cout << "-------------------------" << std::endl;
34 std::cout << "Requires exactly four arguments." << std::endl;
35 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;
37 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;
39 std::cout << "5. Datafile output path." << std::endl;
40
41 exit(1);
42}
43/*
44void parse_group(xmlNodePtr top, std::string filename)
45{
46 xmlChar* key = xmlGetProp(top, (xmlChar*) "ID");
47 if (key == 0)
48 {
49 std::cout << "Bad VerbNet file format: " << filename << std::endl;
50 print_usage();
51 }
52 std::string vnid = key;
53 vnid = vnid.substr(vnid.find_first_of("-")+1);
54 xmlFree(key);
55
56 group g;
57 g.id = vnid;
58
59 for (xmlNodePtr node = top->xmlChildrenNode; node != nullptr; node = node->next)
60 {
61 if (!xmlStrcmp(node->name, (const xmlChar*) "MEMBERS"))
62 {
63 for (xmlNodePtr member = node->xmlChildrenNode; member != nullptr; member = member->next)
64 {
65 if (!xmlStrcmp(member->name, (const xmlChar*) "MEMBER"))
66 {
67 key = xmlGetProp(member, (xmlChar*) "name");
68 g.members.insert(key);
69 xmlFree(key);
70 }
71 }
72 } else if (!xmlStrcmp(node->name, (const xmlChar*) "FRAMES"))
73 {
74 for (xmlNodePtr frame = node->xmlChildrenNode; frame != nullptr; frame = frame->next)
75 {
76 if (!xmlStrcmp(frame->name, (const xmlChar*) "FRAME"))
77 {
78 for (xmlNodePtr framenode = frame->xmlChildrenNode; framenode != nullptr; framenode = framenode->next)
79 {
80
81 }
82 }
83 }
84 }
85 }
86}*/
87
88int main(int argc, char** argv)
89{
90 if (argc != 6)
91 {
92 print_usage();
93 }
94
95 /*DIR* dir;
96 if ((dir = opendir(argv[1])) == nullptr)
97 {
98 std::cout << "Invalid VerbNet data directory." << std::endl;
99
100 print_usage();
101 }
102
103 struct dirent* ent;
104 while ((ent = readdir(dir)) != nullptr)
105 {
106 std::string filename(argv[1]);
107 if (filename.back() != '/')
108 {
109 filename += '/';
110 }
111
112 filename += ent->d_name;
113 //std::cout << ent->d_name << std::endl;
114
115 if (filename.rfind(".xml") != filename.size() - 4)
116 {
117 continue;
118 }
119
120 xmlDocPtr doc = xmlParseFile(filename.c_str());
121 if (doc == nullptr)
122 {
123 std::cout << "Error opening " << filename << std::endl;
124 print_usage();
125 }
126
127 xmlNodePtr top = xmlDocGetRootElement(doc);
128 if ((top == nullptr) || (xmlStrcmp(top->name, (xmlChar*) "VNCLASS")))
129 {
130 std::cout << "Bad VerbNet file format: " << filename << std::endl;
131 print_usage();
132 }
133
134 parse_group(top, filename);
135 }
136
137 closedir(dir);*/
138
139 // Get verbs from AGID
140 std::cout << "Reading verb inflection..." << std::endl;
141
142 std::ifstream agidfile(argv[3]);
143 if (!agidfile.is_open())
144 {
145 std::cout << "Could not open AGID file: " << argv[3] << std::endl;
146 print_usage();
147 }
148
149 for (;;)
150 {
151 std::string line;
152 if (!getline(agidfile, line))
153 {
154 break;
155 }
156
157 if (line.back() == '\r')
158 {
159 line.pop_back();
160 }
161
162 int divider = line.find_first_of(" ");
163 std::string word = line.substr(0, divider);
164 line = line.substr(divider+1);
165
166 if (line[0] != 'V')
167 {
168 continue;
169 }
170
171 if (line[1] == '?')
172 {
173 line.erase(0, 4);
174 } else {
175 line.erase(0, 3);
176 }
177
178 std::vector<std::string> forms;
179 while (!line.empty())
180 {
181 std::string inflection;
182 if ((divider = line.find(" | ")) != std::string::npos)
183 {
184 inflection = line.substr(0, divider);
185 line = line.substr(divider + 3);
186 } else {
187 inflection = line;
188 line = "";
189 }
190
191 if ((divider = inflection.find_first_of(",?")) != std::string::npos)
192 {
193 inflection = inflection.substr(0, divider);
194 }
195
196 forms.push_back(inflection);
197 }
198
199 verb v;
200 v.infinitive = word;
201 if (forms.size() == 4)
202 {
203 v.past_tense = forms[0];
204 v.past_participle = forms[1];
205 v.ing_form = forms[2];
206 v.s_form = forms[3];
207 } else if (forms.size() == 3)
208 {
209 v.past_tense = forms[0];
210 v.past_participle = forms[0];
211 v.ing_form = forms[1];
212 v.s_form = forms[2];
213 } else if (forms.size() == 8)
214 {
215 // As of AGID 2014.08.11, this is only "to be"
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 }
227
228 verbs[word] = v;
229 }
230
231 // Start writing output
232 std::cout << "Writing output..." << std::endl;
233
234 sqlite3* ppdb;
235 if (sqlite3_open_v2(argv[5], &ppdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK)
236 {
237 std::cout << "Error opening output datafile: " << sqlite3_errmsg(ppdb) << std::endl;
238 print_usage();
239 }
240
241 std::ifstream schemafile("schema.sql");
242 if (!schemafile.is_open())
243 {
244 std::cout << "Could not find schema file" << std::endl;
245 print_usage();
246 }
247
248 std::stringstream schemabuilder;
249 for (;;)
250 {
251 std::string line;
252 if (!getline(schemafile, line))
253 {
254 break;
255 }
256
257 if (line.back() == '\r')
258 {
259 line.pop_back();
260 }
261
262 schemabuilder << line << std::endl;
263 }
264
265 std::string schema = schemabuilder.str();
266 while (!schema.empty())
267 {
268 std::string query;
269 int divider = schema.find(";");
270 if (divider != std::string::npos)
271 {
272 query = schema.substr(0, divider+1);
273 schema = schema.substr(divider+2);
274 } else {
275 break;
276 }
277
278 sqlite3_stmt* schmstmt;
279 if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &schmstmt, NULL) != SQLITE_OK)
280 {
281 std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl;
282 sqlite3_close_v2(ppdb);
283 print_usage();
284 }
285
286 if (sqlite3_step(schmstmt) != SQLITE_DONE)
287 {
288 std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl;
289 sqlite3_close_v2(ppdb);
290 print_usage();
291 }
292
293 sqlite3_finalize(schmstmt);
294 }
295
296 std::cout << "Writing verbs..." << std::endl;
297 for (auto& mapping : verbs)
298 {
299 sqlite3_stmt* ppstmt;
300 std::string query("INSERT INTO verbs (infinitive, past_tense, past_participle, ing_form, s_form) VALUES (?, ?, ?, ?, ?)");
301 if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
302 {
303 std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl;
304 sqlite3_close_v2(ppdb);
305 print_usage();
306 }
307
308 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);
310 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);
312 sqlite3_bind_text(ppstmt, 5, mapping.second.s_form.c_str(), mapping.second.s_form.length(), SQLITE_STATIC);
313
314 if (sqlite3_step(ppstmt) != SQLITE_DONE)
315 {
316 std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl;
317 sqlite3_close_v2(ppdb);
318 print_usage();
319 }
320
321 sqlite3_finalize(ppstmt);
322 }
323
324 // Get nouns/adjectives/adverbs from WordNet
325 // Useful relations:
326 // - s: master list
327 // - ant: antonymy (e.g. happy/sad, sad/happy, happiness/sadness)
328 // - at: variation (e.g. a measurement can be standard or nonstandard)
329 // - hyp: hypernymy/hyponymy (e.g. color/red, color/blue)
330 // - ins: instantiation (do we need this? let's see)
331 // - mm: member meronymy/holonymy (e.g. family/mother, family/child)
332 // - mp: part meronymy/holonymy (e.g. wheel/spoke, wheel/tire)
333 // - ms: substance meronymy/holonymy (e.g. tire/rubber, doorstop/rubber)
334 // - per: pertainymy (e.g. something that is Alaskan pertains to Alaska)
335 // mannernymy (e.g. something done quickly is done in a manner that is quick)
336 // - sa: specification (e.g. inaccurate (general) can mean imprecise or incorrect (specific))
337 // - sim: synonymy (e.g. cheerful/happy, happy/cheerful)
338 // - syntax: positioning flags for some adjectives
339 std::string wnpref {argv[4]};
340 if (wnpref.back() != '/')
341 {
342 wnpref += '/';
343 }
344
345 std::cout << "Reading words from WordNet..." << std::endl;
346 std::ifstream wnsfile(wnpref + "wn_s.pl");
347 if (!wnsfile.is_open())
348 {
349 std::cout << "Invalid WordNet data directory." << std::endl;
350 print_usage();
351 }
352
353 for (;;)
354 {
355 std::string line;
356 if (!getline(wnsfile, line))
357 {
358 break;
359 }
360
361 if (line.back() == '\r')
362 {
363 line.pop_back();
364 }
365
366 std::regex relation("^s\\(([134]\\d{8}),(\\d+),'([\\w ]+)',");
367 std::smatch relation_data;
368 if (!std::regex_search(line, relation_data, relation))
369 {
370 continue;
371 }
372
373 int synset_id = stoi(relation_data[1]);
374 int wnum = stoi(relation_data[2]);
375 std::string word = relation_data[3];
376
377 std::string query;
378 switch (synset_id / 100000000)
379 {
380 case 1: // Noun
381 {
382 query = "INSERT INTO nouns (form) VALUES (?)";
383
384 break;
385 }
386
387 case 2: // Verb
388 {
389 // Ignore
390
391 break;
392 }
393
394 case 3: // Adjective
395 {
396 query = "INSERT INTO adjectives (form) VALUES (?)";
397
398 break;
399 }
400
401 case 4: // Adverb
402 {
403 query = "INSERT INTO adverbs (form) VALUES (?)";
404
405 break;
406 }
407 }
408
409 sqlite3_stmt* ppstmt;
410 if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
411 {
412 std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl;
413 sqlite3_close_v2(ppdb);
414 print_usage();
415 }
416
417 sqlite3_bind_text(ppstmt, 1, word.c_str(), word.length(), SQLITE_STATIC);
418
419 if (sqlite3_step(ppstmt) != SQLITE_DONE)
420 {
421 std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl;
422 sqlite3_close_v2(ppdb);
423 print_usage();
424 }
425
426 sqlite3_finalize(ppstmt);
427
428 query = "SELECT last_insert_rowid()";
429 if (sqlite3_prepare_v2(ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK)
430 {
431 std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl;
432 sqlite3_close_v2(ppdb);
433 print_usage();
434 }
435
436 if (sqlite3_step(ppstmt) != SQLITE_ROW)
437 {
438 std::cout << "Error writing to output database: " << sqlite3_errmsg(ppdb) << std::endl;
439 sqlite3_close_v2(ppdb);
440 print_usage();
441 }
442
443 wn[synset_id][wnum] = sqlite3_column_int(ppstmt, 0);
444
445 sqlite3_finalize(ppstmt);
446 }
447
448 sqlite3_close_v2(ppdb);
449
450 std::cout << "Done." << std::endl;
451} \ No newline at end of file
diff --git a/schema.sql b/schema.sql index 7c1b52c..62dd780 100644 --- a/schema.sql +++ b/schema.sql
@@ -34,5 +34,122 @@ CREATE TABLE `verb_groups` (
34DROP TABLE IF EXISTS `adjectives`; 34DROP TABLE IF EXISTS `adjectives`;
35CREATE TABLE `adjectives` ( 35CREATE TABLE `adjectives` (
36 `adjective_id` INTEGER PRIMARY KEY, 36 `adjective_id` INTEGER PRIMARY KEY,
37 `adjective` VARCHAR(32) NOT NULL 37 `form` VARCHAR(32) NOT NULL,
38); \ No newline at end of file 38 `position` CHAR(1)
39);
40
41DROP TABLE IF EXISTS `adverbs`;
42CREATE TABLE `adverbs` (
43 `adverb_id` INTEGER PRIMARY KEY,
44 `form` VARCHAR(32) NOT NULL
45);
46
47DROP TABLE IF EXISTS `nouns`;
48CREATE TABLE `nouns` (
49 `noun_id` INTEGER PRIMARY KEY,
50 `form` VARCHAR(32) NOT NULL
51);
52
53DROP TABLE IF EXISTS `hypernymy`;
54CREATE TABLE `hypernymy` (
55 `hypernym_id` INTEGER NOT NULL,
56 `hyponym_id` INTEGER NOT NULL,
57 FOREIGN KEY (`hypernym_id`) REFERENCES `nouns`(`noun_id`),
58 FOREIGN KEY (`hyponym_id`) REFERENCES `nouns`(`noun_id`)
59);
60
61DROP TABLE IF EXISTS `instantiation`;
62CREATE TABLE `instantiation` (
63 `class_id` INTEGER NOT NULL,
64 `instance_id` INTEGER NOT NULL,
65 FOREIGN KEY (`class_id`) REFERENCES `nouns`(`noun_id`),
66 FOREIGN KEY (`instance_id`) REFERENCES `nouns`(`noun_id`)
67);
68
69DROP TABLE IF EXISTS `member_meronymy`;
70CREATE TABLE `member_meronymy` (
71 `meronym_id` INTEGER NOT NULL,
72 `holonym_id` INTEGER NOT NULL,
73 FOREIGN KEY (`meronym_id`) REFERENCES `nouns`(`noun_id`),
74 FOREIGN KEY (`holonym_id`) REFERENCES `nouns`(`noun_id`)
75);
76
77DROP TABLE IF EXISTS `part_meronymy`;
78CREATE TABLE `part_meronymy` (
79 `meronym_id` INTEGER NOT NULL,
80 `holonym_id` INTEGER NOT NULL,
81 FOREIGN KEY (`meronym_id`) REFERENCES `nouns`(`noun_id`),
82 FOREIGN KEY (`holonym_id`) REFERENCES `nouns`(`noun_id`)
83);
84
85DROP TABLE IF EXISTS `substance_meronymy`;
86CREATE TABLE `substance_meronymy` (
87 `meronym_id` INTEGER NOT NULL,
88 `holonym_id` INTEGER NOT NULL,
89 FOREIGN KEY (`meronym_id`) REFERENCES `nouns`(`noun_id`),
90 FOREIGN KEY (`holonym_id`) REFERENCES `nouns`(`noun_id`)
91);
92
93DROP TABLE IF EXISTS `variation`;
94CREATE TABLE `variation` (
95 `noun_id` INTEGER NOT NULL,
96 `adjective_id` INTEGER NOT NULL,
97 FOREIGN KEY (`noun_id`) REFERENCES `nouns`(`noun_id`),
98 FOREIGN KEY (`adjective_id`) REFERENCES `adjectives`(`adjective_id`)
99);
100
101DROP TABLE IF EXISTS `noun_antonymy`;
102CREATE TABLE `noun_antonymy` (
103 `noun_1_id` INTEGER NOT NULL,
104 `noun_2_id` INTEGER NOT NULL,
105 FOREIGN KEY (`noun_1_id`) REFERENCES `nouns`(`noun_id`),
106 FOREIGN KEY (`noun_2_id`) REFERENCES `nouns`(`noun_id`)
107);
108
109DROP TABLE IF EXISTS `adjective_antonymy`;
110CREATE TABLE `adjective_antonymy` (
111 `adjective_1_id` INTEGER NOT NULL,
112 `adjective_2_id` INTEGER NOT NULL,
113 FOREIGN KEY (`adjective_1_id`) REFERENCES `adjectives`(`adjective_id`),
114 FOREIGN KEY (`adjective_2_id`) REFERENCES `adjectives`(`adjective_id`)
115);
116
117DROP TABLE IF EXISTS `adverb_antonymy`;
118CREATE TABLE `adverb_antonymy` (
119 `adverb_1_id` INTEGER NOT NULL,
120 `adverb_2_id` INTEGER NOT NULL,
121 FOREIGN KEY (`adverb_1_id`) REFERENCES `adverbs`(`adverb_id`),
122 FOREIGN KEY (`adverb_2_id`) REFERENCES `adverbs`(`adverb_id`)
123);
124
125DROP TABLE IF EXISTS `specification`;
126CREATE TABLE `specification` (
127 `general_id` INTEGER NOT NULL,
128 `specific_id` INTEGER NOT NULL,
129 FOREIGN KEY (`general_id`) REFERENCES `adjectives`(`adjective_id`),
130 FOREIGN KEY (`specific_id`) REFERENCES `adjectives`(`adjective_id`)
131);
132
133DROP TABLE IF EXISTS `pertainymy`;
134CREATE TABLE `pertainymy` (
135 `noun_id` INTEGER NOT NULL,
136 `pertainym_id` INTEGER NOT NULL,
137 FOREIGN KEY (`noun_id`) REFERENCES `nouns`(`noun_id`),
138 FOREIGN KEY (`pertainym_id`) REFERENCES `adjectives`(`adjective_id`)
139);
140
141DROP TABLE IF EXISTS `mannernymy`;
142CREATE TABLE `mannernymy` (
143 `adjective_id` INTEGER NOT NULL,
144 `mannernym_id` INTEGER NOT NULL,
145 FOREIGN KEY (`adjective_id`) REFERENCES `adjectives`(`adjective_id`),
146 FOREIGN KEY (`mannernym_id`) REFERENCES `adverbs`(`adverb_id`)
147);
148
149DROP TABLE IF EXISTS `synonymy`;
150CREATE TABLE `synonymy` (
151 `adjective_1_id` INTEGER NOT NULL,
152 `adjective_2_id` INTEGER NOT NULL,
153 FOREIGN KEY (`adjective_1_id`) REFERENCES `adjectives`(`adjective_id`),
154 FOREIGN KEY (`adjective_2_id`) REFERENCES `adjectives`(`adjective_id`)
155);
diff --git a/verbly/adjective.h b/verbly/adjective.h index 58c490e..9d7883f 100644 --- a/verbly/adjective.h +++ b/verbly/adjective.h
@@ -8,7 +8,7 @@ namespace verbly {
8 int id; 8 int id;
9 9
10 public: 10 public:
11 std::string value; 11 std::string form;
12 12
13 adjective(int id) : id(id) 13 adjective(int id) : id(id)
14 { 14 {
diff --git a/verbly/adverb.h b/verbly/adverb.h new file mode 100644 index 0000000..6d2466e --- /dev/null +++ b/verbly/adverb.h
@@ -0,0 +1,21 @@
1#ifndef ADVERB_H_86F8302F
2#define ADVERB_H_86F8302F
3
4namespace verbly {
5
6 class adverb {
7 private:
8 int id;
9
10 public:
11 std::string form;
12
13 adverb(int id) : id(id)
14 {
15
16 }
17 };
18
19};
20
21#endif /* end of include guard: ADVERB_H_86F8302F */
diff --git a/verbly/data.h b/verbly/data.h index 2c23c15..e901cba 100644 --- a/verbly/data.h +++ b/verbly/data.h
@@ -121,7 +121,7 @@ namespace verbly {
121 std::list<adjective> run() const 121 std::list<adjective> run() const
122 { 122 {
123 std::stringstream construct; 123 std::stringstream construct;
124 construct << "SELECT adjective_id, adjective FROM adjectives"; 124 construct << "SELECT adjective_id, form FROM adjectives";
125 125
126 if (m_random) 126 if (m_random)
127 { 127 {
@@ -144,7 +144,77 @@ namespace verbly {
144 while (sqlite3_step(ppstmt) == SQLITE_ROW) 144 while (sqlite3_step(ppstmt) == SQLITE_ROW)
145 { 145 {
146 adjective tnc {sqlite3_column_int(ppstmt, 0)}; 146 adjective tnc {sqlite3_column_int(ppstmt, 0)};
147 tnc.value = std::string(reinterpret_cast<const char*>(sqlite3_column_text(ppstmt, 1))); 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)));
148 218
149 output.push_back(tnc); 219 output.push_back(tnc);
150 } 220 }
@@ -194,6 +264,11 @@ namespace verbly {
194 return adjective_query(*this); 264 return adjective_query(*this);
195 } 265 }
196 266
267 adverb_query adverbs() const
268 {
269 return adverb_query(*this);
270 }
271
197 }; 272 };
198 273
199}; 274};
diff --git a/verbly/token.h b/verbly/token.h index bbe7c2d..2848fd0 100644 --- a/verbly/token.h +++ b/verbly/token.h
@@ -24,7 +24,8 @@ namespace verbly {
24 enum class fillin_type { 24 enum class fillin_type {
25 noun_phrase, 25 noun_phrase,
26 participle_phrase, 26 participle_phrase,
27 adjective 27 adjective,
28 adverb
28 }; 29 };
29 30
30 class token { 31 class token {
@@ -128,14 +129,14 @@ namespace verbly {
128 return it != other.it; 129 return it != other.it;
129 } 130 }
130 131
131 token* operator*() 132 token& operator*()
132 { 133 {
133 return *it->get(); 134 return **it;
134 } 135 }
135 136
136 token* operator->() 137 token& operator->()
137 { 138 {
138 return *it->get(); 139 return **it;
139 } 140 }
140 };*/ 141 };*/
141 142
@@ -189,16 +190,6 @@ namespace verbly {
189 return std::end(utterance); 190 return std::end(utterance);
190 } 191 }
191 192
192 const iterator begin() const
193 {
194 return std::begin(utterance);
195 }
196
197 const iterator end() const
198 {
199 return std::end(utterance);
200 }
201
202 void erase(iterator it) 193 void erase(iterator it)
203 { 194 {
204 utterance.erase(it); 195 utterance.erase(it);
diff --git a/verbly/verbly.h b/verbly/verbly.h index 139d8f8..44fd3a8 100644 --- a/verbly/verbly.h +++ b/verbly/verbly.h
@@ -5,6 +5,7 @@
5#include "token.h" 5#include "token.h"
6#include "verb.h" 6#include "verb.h"
7#include "adjective.h" 7#include "adjective.h"
8#include "adverb.h"
8#include "data.h" 9#include "data.h"
9 10
10#endif /* end of include guard: VERBLY_H_5B39CE50 */ 11#endif /* end of include guard: VERBLY_H_5B39CE50 */