diff options
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | lib/frame.cpp | 89 | ||||
| -rw-r--r-- | lib/frame.h | 60 | ||||
| -rw-r--r-- | lib/frame_query.cpp | 166 | ||||
| -rw-r--r-- | lib/frame_query.h | 21 | ||||
| -rw-r--r-- | lib/group.cpp | 44 | ||||
| -rw-r--r-- | lib/group.h | 60 | ||||
| -rw-r--r-- | lib/part.cpp | 344 | ||||
| -rw-r--r-- | lib/part.h | 117 |
9 files changed, 643 insertions, 260 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index 61fcce2..8d42fdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -7,7 +7,7 @@ pkg_check_modules(sqlite3 sqlite3>=3.8.3 REQUIRED) | |||
| 7 | set(CMAKE_BUILD_TYPE Debug) | 7 | set(CMAKE_BUILD_TYPE Debug) |
| 8 | 8 | ||
| 9 | include_directories(vendor/json) | 9 | include_directories(vendor/json) |
| 10 | add_library(verbly lib/filter.cpp lib/field.cpp lib/notion.cpp lib/word.cpp lib/group.cpp lib/frame.cpp lib/lemma.cpp lib/form.cpp lib/pronunciation.cpp lib/statement.cpp lib/binding.cpp lib/database.cpp) | 10 | add_library(verbly lib/filter.cpp lib/field.cpp lib/notion.cpp lib/word.cpp lib/group.cpp lib/frame.cpp lib/lemma.cpp lib/form.cpp lib/pronunciation.cpp lib/statement.cpp lib/binding.cpp lib/database.cpp lib/selrestr.cpp lib/part.cpp) |
| 11 | set_property(TARGET verbly PROPERTY CXX_STANDARD 11) | 11 | set_property(TARGET verbly PROPERTY CXX_STANDARD 11) |
| 12 | set_property(TARGET verbly PROPERTY CXX_STANDARD_REQUIRED ON) | 12 | set_property(TARGET verbly PROPERTY CXX_STANDARD_REQUIRED ON) |
| 13 | target_link_libraries(verbly ${sqlite3_LIBRARIES}) | 13 | target_link_libraries(verbly ${sqlite3_LIBRARIES}) |
| diff --git a/lib/frame.cpp b/lib/frame.cpp index bc3f842..3ce95ec 100644 --- a/lib/frame.cpp +++ b/lib/frame.cpp | |||
| @@ -1,21 +1,96 @@ | |||
| 1 | #include "frame.h" | 1 | #include "frame.h" |
| 2 | #include <sqlite3.h> | 2 | #include <sqlite3.h> |
| 3 | #include <json.hpp> | ||
| 3 | 4 | ||
| 4 | namespace verbly { | 5 | namespace verbly { |
| 5 | 6 | ||
| 6 | const object frame::objectType = object::frame; | 7 | const object frame::objectType = object::frame; |
| 7 | 8 | ||
| 8 | const std::list<std::string> frame::select = {"frame_id", "data"}; | 9 | const std::list<std::string> frame::select = {"frame_id", "data"}; |
| 9 | 10 | ||
| 10 | const field frame::id = field::integerField(object::frame, "frame_id"); | 11 | const field frame::id = field::integerField(object::frame, "frame_id"); |
| 11 | 12 | ||
| 12 | const field frame::group = field::joinThrough(object::frame, "frame_id", object::group, "groups_frames", "group_id"); | 13 | const field frame::group = field::joinThrough(object::frame, "frame_id", object::group, "groups_frames", "group_id"); |
| 13 | 14 | ||
| 14 | frame::frame(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) | 15 | frame::frame(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) |
| 15 | { | 16 | { |
| 16 | id_ = sqlite3_column_int(row, 0); | 17 | id_ = sqlite3_column_int(row, 0); |
| 17 | 18 | ||
| 18 | // TODO: Initialize frame data from row. | 19 | // TODO: Initialize frame data from row. |
| 20 | std::string partsJsonStr(reinterpret_cast<const char*>(sqlite3_column_blob(row, 1))); | ||
| 21 | nlohmann::json partsJson = nlohmann::json::parse(std::move(partsJsonStr)); | ||
| 22 | |||
| 23 | for (const nlohmann::json& partJson : partsJson) | ||
| 24 | { | ||
| 25 | part::type partType = static_cast<part::type>(partJson["type"].get<int>()); | ||
| 26 | |||
| 27 | switch (partType) | ||
| 28 | { | ||
| 29 | case part::type::noun_phrase: | ||
| 30 | { | ||
| 31 | std::set<std::string> synrestrs; | ||
| 32 | for (const nlohmann::json& synrestrJson : partJson["synrestrs"]) | ||
| 33 | { | ||
| 34 | synrestrs.insert(synrestrJson.get<std::string>()); | ||
| 35 | } | ||
| 36 | |||
| 37 | parts_.push_back(part::createNounPhrase( | ||
| 38 | partJson["role"].get<std::string>(), | ||
| 39 | selrestr(partJson["selrestrs"]), | ||
| 40 | std::move(synrestrs))); | ||
| 41 | |||
| 42 | break; | ||
| 43 | } | ||
| 44 | |||
| 45 | case part::type::preposition: | ||
| 46 | { | ||
| 47 | std::vector<std::string> choices; | ||
| 48 | for (const nlohmann::json& choiceJson : partJson["choices"]) | ||
| 49 | { | ||
| 50 | choices.push_back(choiceJson.get<std::string>()); | ||
| 51 | } | ||
| 52 | |||
| 53 | parts_.push_back(part::createPreposition( | ||
| 54 | std::move(choices), | ||
| 55 | partJson["literal"].get<bool>())); | ||
| 56 | |||
| 57 | break; | ||
| 58 | } | ||
| 59 | |||
| 60 | case part::type::verb: | ||
| 61 | { | ||
| 62 | parts_.push_back(part::createVerb()); | ||
| 63 | |||
| 64 | break; | ||
| 65 | } | ||
| 66 | |||
| 67 | case part::type::adjective: | ||
| 68 | { | ||
| 69 | parts_.push_back(part::createAdjective()); | ||
| 70 | |||
| 71 | break; | ||
| 72 | } | ||
| 73 | |||
| 74 | case part::type::adverb: | ||
| 75 | { | ||
| 76 | parts_.push_back(part::createAdverb()); | ||
| 77 | |||
| 78 | break; | ||
| 79 | } | ||
| 80 | |||
| 81 | case part::type::literal: | ||
| 82 | { | ||
| 83 | parts_.push_back(part::createLiteral(partJson["value"].get<std::string>())); | ||
| 84 | |||
| 85 | break; | ||
| 86 | } | ||
| 87 | |||
| 88 | case part::type::invalid: | ||
| 89 | { | ||
| 90 | throw std::domain_error("Invalid part data"); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | } | ||
| 19 | } | 94 | } |
| 20 | 95 | ||
| 21 | }; | 96 | }; |
| diff --git a/lib/frame.h b/lib/frame.h index 68a4346..97473a0 100644 --- a/lib/frame.h +++ b/lib/frame.h | |||
| @@ -5,74 +5,86 @@ | |||
| 5 | #include <list> | 5 | #include <list> |
| 6 | #include "field.h" | 6 | #include "field.h" |
| 7 | #include "filter.h" | 7 | #include "filter.h" |
| 8 | #include "part.h" | ||
| 8 | 9 | ||
| 9 | struct sqlite3_stmt; | 10 | struct sqlite3_stmt; |
| 10 | 11 | ||
| 11 | namespace verbly { | 12 | namespace verbly { |
| 12 | 13 | ||
| 13 | class database; | 14 | class database; |
| 14 | 15 | ||
| 15 | class frame { | 16 | class frame { |
| 16 | public: | 17 | public: |
| 17 | 18 | ||
| 18 | // Default constructor | 19 | // Default constructor |
| 19 | 20 | ||
| 20 | frame() = default; | 21 | frame() = default; |
| 21 | 22 | ||
| 22 | // Construct from database | 23 | // Construct from database |
| 23 | 24 | ||
| 24 | frame(const database& db, sqlite3_stmt* row); | 25 | frame(const database& db, sqlite3_stmt* row); |
| 25 | 26 | ||
| 26 | // Accessors | 27 | // Accessors |
| 27 | 28 | ||
| 28 | operator bool() const | 29 | operator bool() const |
| 29 | { | 30 | { |
| 30 | return valid_; | 31 | return valid_; |
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | int getId() const | 34 | int getId() const |
| 34 | { | 35 | { |
| 35 | if (!valid_) | 36 | if (!valid_) |
| 36 | { | 37 | { |
| 37 | throw std::domain_error("Bad access to uninitialized frame"); | 38 | throw std::domain_error("Bad access to uninitialized frame"); |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | return id_; | 41 | return id_; |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 44 | const std::vector<part>& getParts() const | ||
| 45 | { | ||
| 46 | if (!valid_) | ||
| 47 | { | ||
| 48 | throw std::domain_error("Bad access to uninitialized frame"); | ||
| 49 | } | ||
| 50 | |||
| 51 | return parts_; | ||
| 52 | } | ||
| 53 | |||
| 43 | // Type info | 54 | // Type info |
| 44 | 55 | ||
| 45 | static const object objectType; | 56 | static const object objectType; |
| 46 | 57 | ||
| 47 | static const std::list<std::string> select; | 58 | static const std::list<std::string> select; |
| 48 | 59 | ||
| 49 | // Query fields | 60 | // Query fields |
| 50 | 61 | ||
| 51 | static const field id; | 62 | static const field id; |
| 52 | 63 | ||
| 53 | operator filter() const | 64 | operator filter() const |
| 54 | { | 65 | { |
| 55 | if (!valid_) | 66 | if (!valid_) |
| 56 | { | 67 | { |
| 57 | throw std::domain_error("Bad access to uninitialized frame"); | 68 | throw std::domain_error("Bad access to uninitialized frame"); |
| 58 | } | 69 | } |
| 59 | 70 | ||
| 60 | return (id == id_); | 71 | return (id == id_); |
| 61 | } | 72 | } |
| 62 | 73 | ||
| 63 | // Relationships to other objects | 74 | // Relationships to other objects |
| 64 | 75 | ||
| 65 | static const field group; | 76 | static const field group; |
| 66 | 77 | ||
| 67 | private: | 78 | private: |
| 68 | bool valid_ = false; | 79 | bool valid_ = false; |
| 69 | 80 | ||
| 70 | int id_; | 81 | int id_; |
| 71 | 82 | std::vector<part> parts_; | |
| 83 | |||
| 72 | const database* db_; | 84 | const database* db_; |
| 73 | 85 | ||
| 74 | }; | 86 | }; |
| 75 | 87 | ||
| 76 | }; | 88 | }; |
| 77 | 89 | ||
| 78 | #endif /* end of include guard: FRAME_H_EA29065A */ | 90 | #endif /* end of include guard: FRAME_H_EA29065A */ |
| diff --git a/lib/frame_query.cpp b/lib/frame_query.cpp deleted file mode 100644 index 11f0432..0000000 --- a/lib/frame_query.cpp +++ /dev/null | |||
| @@ -1,166 +0,0 @@ | |||
| 1 | #include "verbly.h" | ||
| 2 | #include <json.hpp> | ||
| 3 | |||
| 4 | using json = nlohmann::json; | ||
| 5 | |||
| 6 | namespace verbly { | ||
| 7 | |||
| 8 | frame_query::frame_query(const data& _data) : _data(_data) | ||
| 9 | { | ||
| 10 | |||
| 11 | } | ||
| 12 | |||
| 13 | frame_query& frame_query::for_verb(const verb& _v) | ||
| 14 | { | ||
| 15 | _for_verb.push_back(_v); | ||
| 16 | |||
| 17 | return *this; | ||
| 18 | } | ||
| 19 | |||
| 20 | frame::selrestr parse_selrestr(const json data) | ||
| 21 | { | ||
| 22 | if (data.find("children") != data.end()) | ||
| 23 | { | ||
| 24 | std::list<frame::selrestr> children; | ||
| 25 | std::transform(std::begin(data["children"]), std::end(data["children"]), std::back_inserter(children), &parse_selrestr); | ||
| 26 | |||
| 27 | return frame::selrestr{children, data["logic"] == "or"}; | ||
| 28 | } else if (data.find("type") != data.end()) | ||
| 29 | { | ||
| 30 | return frame::selrestr{data["type"].get<std::string>(), data["pos"].get<bool>()}; | ||
| 31 | } else { | ||
| 32 | return frame::selrestr{}; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | std::list<frame> frame_query::run() const | ||
| 37 | { | ||
| 38 | std::stringstream construct; | ||
| 39 | construct << "SELECT frames.data, groups.data FROM frames INNER JOIN groups ON frames.group_id = groups.group_id"; | ||
| 40 | std::list<binding> bindings; | ||
| 41 | |||
| 42 | if (!_for_verb.empty()) | ||
| 43 | { | ||
| 44 | std::list<std::string> clauses(_for_verb.size(), "verb_id = ?"); | ||
| 45 | construct << " WHERE frames.group_id IN (SELECT group_id FROM verb_groups WHERE "; | ||
| 46 | construct << verbly::implode(std::begin(clauses), std::end(clauses), " OR "); | ||
| 47 | construct << ")"; | ||
| 48 | |||
| 49 | for (auto v : _for_verb) | ||
| 50 | { | ||
| 51 | bindings.emplace_back(v._id); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | sqlite3_stmt* ppstmt; | ||
| 56 | std::string query = construct.str(); | ||
| 57 | if (sqlite3_prepare_v2(_data.ppdb, query.c_str(), query.length(), &ppstmt, NULL) != SQLITE_OK) | ||
| 58 | { | ||
| 59 | throw std::runtime_error(sqlite3_errmsg(_data.ppdb)); | ||
| 60 | } | ||
| 61 | |||
| 62 | int i = 1; | ||
| 63 | for (auto& binding : bindings) | ||
| 64 | { | ||
| 65 | switch (binding.get_type()) | ||
| 66 | { | ||
| 67 | case binding::type::integer: | ||
| 68 | { | ||
| 69 | sqlite3_bind_int(ppstmt, i, binding.get_integer()); | ||
| 70 | |||
| 71 | break; | ||
| 72 | } | ||
| 73 | |||
| 74 | case binding::type::string: | ||
| 75 | { | ||
| 76 | sqlite3_bind_text(ppstmt, i, binding.get_string().c_str(), binding.get_string().length(), SQLITE_TRANSIENT); | ||
| 77 | |||
| 78 | break; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | i++; | ||
| 83 | } | ||
| 84 | |||
| 85 | std::list<frame> output; | ||
| 86 | while (sqlite3_step(ppstmt) == SQLITE_ROW) | ||
| 87 | { | ||
| 88 | frame f; | ||
| 89 | |||
| 90 | std::string fdatat(reinterpret_cast<const char*>(sqlite3_column_blob(ppstmt, 0))); | ||
| 91 | const json fdata = json::parse(fdatat); | ||
| 92 | for (const auto& part : fdata) | ||
| 93 | { | ||
| 94 | frame::part p; | ||
| 95 | |||
| 96 | if (part["type"] == "np") | ||
| 97 | { | ||
| 98 | p._type = frame::part::type::noun_phrase; | ||
| 99 | new(&p._noun_phrase.role) std::string(part["role"].get<std::string>()); | ||
| 100 | new(&p._noun_phrase.selrestrs) frame::selrestr(parse_selrestr(part["selrestrs"])); | ||
| 101 | new(&p._noun_phrase.synrestrs) std::set<std::string>(); | ||
| 102 | for (auto synrestr : part["synrestrs"]) | ||
| 103 | { | ||
| 104 | p._noun_phrase.synrestrs.insert(synrestr.get<std::string>()); | ||
| 105 | } | ||
| 106 | } else if (part["type"] == "pp") | ||
| 107 | { | ||
| 108 | if (!part["values"].empty()) | ||
| 109 | { | ||
| 110 | p._type = frame::part::type::literal_preposition; | ||
| 111 | new(&p._literal_preposition.choices) std::vector<std::string>(); | ||
| 112 | for (auto choice : part["values"]) | ||
| 113 | { | ||
| 114 | p._literal_preposition.choices.push_back(choice.get<std::string>()); | ||
| 115 | } | ||
| 116 | } else if (!part["preprestrs"].empty()) | ||
| 117 | { | ||
| 118 | p._type = frame::part::type::selection_preposition; | ||
| 119 | new(&p._selection_preposition.preprestrs) std::vector<std::string>(); | ||
| 120 | for (auto preprestr : part["preprestrs"]) | ||
| 121 | { | ||
| 122 | p._selection_preposition.preprestrs.push_back(preprestr.get<std::string>()); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } else if (part["type"] == "v") | ||
| 126 | { | ||
| 127 | p._type = frame::part::type::verb; | ||
| 128 | } else if (part["type"] == "adj") | ||
| 129 | { | ||
| 130 | p._type = frame::part::type::adjective; | ||
| 131 | } else if (part["type"] == "adv") | ||
| 132 | { | ||
| 133 | p._type = frame::part::type::adverb; | ||
| 134 | } else if (part["type"] == "lex") | ||
| 135 | { | ||
| 136 | p._type = frame::part::type::literal; | ||
| 137 | new(&p._literal.lexval) std::string(part["value"].get<std::string>()); | ||
| 138 | } | ||
| 139 | |||
| 140 | f._parts.push_back(p); | ||
| 141 | } | ||
| 142 | |||
| 143 | std::string rdatat(reinterpret_cast<const char*>(sqlite3_column_blob(ppstmt, 1))); | ||
| 144 | const json rdata = json::parse(rdatat); | ||
| 145 | for (const auto& role : rdata) | ||
| 146 | { | ||
| 147 | std::string rt = role["type"]; | ||
| 148 | frame::selrestr rs; | ||
| 149 | |||
| 150 | if (role.find("selrestrs") != role.end()) | ||
| 151 | { | ||
| 152 | rs = parse_selrestr(role["selrestrs"]); | ||
| 153 | } | ||
| 154 | |||
| 155 | f._roles[rt] = rs; | ||
| 156 | } | ||
| 157 | |||
| 158 | output.push_back(f); | ||
| 159 | } | ||
| 160 | |||
| 161 | sqlite3_finalize(ppstmt); | ||
| 162 | |||
| 163 | return output; | ||
| 164 | } | ||
| 165 | |||
| 166 | }; | ||
| diff --git a/lib/frame_query.h b/lib/frame_query.h deleted file mode 100644 index dd11d16..0000000 --- a/lib/frame_query.h +++ /dev/null | |||
| @@ -1,21 +0,0 @@ | |||
| 1 | #ifndef FRAME_QUERY_H_334B9D47 | ||
| 2 | #define FRAME_QUERY_H_334B9D47 | ||
| 3 | |||
| 4 | namespace verbly { | ||
| 5 | |||
| 6 | class frame_query { | ||
| 7 | public: | ||
| 8 | frame_query(const data& _data); | ||
| 9 | |||
| 10 | frame_query& for_verb(const verb& _v); | ||
| 11 | |||
| 12 | std::list<frame> run() const; | ||
| 13 | |||
| 14 | private: | ||
| 15 | const data& _data; | ||
| 16 | std::list<verb> _for_verb; | ||
| 17 | }; | ||
| 18 | |||
| 19 | }; | ||
| 20 | |||
| 21 | #endif /* end of include guard: FRAME_QUERY_H_334B9D47 */ | ||
| diff --git a/lib/group.cpp b/lib/group.cpp index 8b6d985..d5790e9 100644 --- a/lib/group.cpp +++ b/lib/group.cpp | |||
| @@ -1,43 +1,61 @@ | |||
| 1 | #include "group.h" | 1 | #include "group.h" |
| 2 | #include <sqlite3.h> | 2 | #include <sqlite3.h> |
| 3 | #include "frame.h" | 3 | #include <json.hpp> |
| 4 | #include "database.h" | 4 | #include "database.h" |
| 5 | #include "query.h" | 5 | #include "query.h" |
| 6 | 6 | ||
| 7 | namespace verbly { | 7 | namespace verbly { |
| 8 | 8 | ||
| 9 | const object group::objectType = object::group; | 9 | const object group::objectType = object::group; |
| 10 | 10 | ||
| 11 | const std::list<std::string> group::select = {"group_id", "data"}; | 11 | const std::list<std::string> group::select = {"group_id", "data"}; |
| 12 | 12 | ||
| 13 | const field group::id = field::integerField(object::group, "group_id"); | 13 | const field group::id = field::integerField(object::group, "group_id"); |
| 14 | 14 | ||
| 15 | const field group::frame = field::joinThrough(object::group, "group_id", object::frame, "groups_frames", "frame_id"); | 15 | const field group::frame = field::joinThrough(object::group, "group_id", object::frame, "groups_frames", "frame_id"); |
| 16 | const field group::word = field::joinField(object::group, "group_id", object::word); | 16 | const field group::word = field::joinField(object::group, "group_id", object::word); |
| 17 | 17 | ||
| 18 | group::group(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) | 18 | group::group(const database& db, sqlite3_stmt* row) : db_(&db), valid_(true) |
| 19 | { | 19 | { |
| 20 | id_ = sqlite3_column_int(row, 0); | 20 | id_ = sqlite3_column_int(row, 0); |
| 21 | 21 | ||
| 22 | // TODO: Initialize role data from row. | 22 | std::string rolesJsonStr(reinterpret_cast<const char*>(sqlite3_column_blob(row, 1))); |
| 23 | nlohmann::json rolesJson = nlohmann::json::parse(std::move(rolesJsonStr)); | ||
| 24 | for (const nlohmann::json& roleJson : rolesJson) | ||
| 25 | { | ||
| 26 | std::string roleName = roleJson["type"]; | ||
| 27 | selrestr roleSelrestr; | ||
| 28 | |||
| 29 | if (roleJson.find("selrestrs") != roleJson.end()) | ||
| 30 | { | ||
| 31 | roleSelrestr = selrestr(roleJson["selrestrs"]); | ||
| 32 | } | ||
| 33 | |||
| 34 | roles_[roleName] = role(roleName, std::move(roleSelrestr)); | ||
| 35 | } | ||
| 23 | } | 36 | } |
| 24 | 37 | ||
| 25 | const std::vector<frame>& group::getFrames() const | 38 | const std::vector<frame>& group::getFrames() const |
| 26 | { | 39 | { |
| 27 | if (!valid_) | 40 | if (!valid_) |
| 28 | { | 41 | { |
| 29 | throw std::domain_error("Bad access to uninitialized group"); | 42 | throw std::domain_error("Bad access to uninitialized group"); |
| 30 | } | 43 | } |
| 31 | 44 | ||
| 32 | if (!initializedFrames_) | 45 | if (!initializedFrames_) |
| 33 | { | 46 | { |
| 34 | frames_ = db_->frames(frame::group %= *this, false, -1).all(); | 47 | frames_ = db_->frames(frame::group %= *this, false, -1).all(); |
| 35 | 48 | ||
| 36 | initializedFrames_ = true; | 49 | initializedFrames_ = true; |
| 37 | } | 50 | } |
| 38 | 51 | ||
| 39 | return frames_; | 52 | return frames_; |
| 40 | } | 53 | } |
| 41 | 54 | ||
| 55 | const role& group::getRole(std::string roleName) const | ||
| 56 | { | ||
| 57 | return roles_.at(roleName); | ||
| 58 | } | ||
| 59 | |||
| 42 | }; | 60 | }; |
| 43 | 61 | ||
| diff --git a/lib/group.h b/lib/group.h index dd53503..fe62d39 100644 --- a/lib/group.h +++ b/lib/group.h | |||
| @@ -6,82 +6,86 @@ | |||
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | #include "field.h" | 7 | #include "field.h" |
| 8 | #include "filter.h" | 8 | #include "filter.h" |
| 9 | #include "frame.h" | ||
| 10 | #include "role.h" | ||
| 9 | 11 | ||
| 10 | struct sqlite3_stmt; | 12 | struct sqlite3_stmt; |
| 11 | 13 | ||
| 12 | namespace verbly { | 14 | namespace verbly { |
| 13 | 15 | ||
| 14 | class database; | 16 | class database; |
| 15 | class frame; | 17 | |
| 16 | |||
| 17 | class group { | 18 | class group { |
| 18 | public: | 19 | public: |
| 19 | 20 | ||
| 20 | // Default constructor | 21 | // Default constructor |
| 21 | 22 | ||
| 22 | group() = default; | 23 | group() = default; |
| 23 | 24 | ||
| 24 | // Construct from database | 25 | // Construct from database |
| 25 | 26 | ||
| 26 | group(const database& db, sqlite3_stmt* row); | 27 | group(const database& db, sqlite3_stmt* row); |
| 27 | 28 | ||
| 28 | // Accessors | 29 | // Accessors |
| 29 | 30 | ||
| 30 | operator bool() const | 31 | operator bool() const |
| 31 | { | 32 | { |
| 32 | return valid_; | 33 | return valid_; |
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | int getId() const | 36 | int getId() const |
| 36 | { | 37 | { |
| 37 | if (!valid_) | 38 | if (!valid_) |
| 38 | { | 39 | { |
| 39 | throw std::domain_error("Bad access to uninitialized group"); | 40 | throw std::domain_error("Bad access to uninitialized group"); |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | return id_; | 43 | return id_; |
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | const std::vector<frame>& getFrames() const; | 46 | const std::vector<frame>& getFrames() const; |
| 46 | 47 | ||
| 48 | const role& getRole(std::string roleName) const; | ||
| 49 | |||
| 47 | // Type info | 50 | // Type info |
| 48 | 51 | ||
| 49 | static const object objectType; | 52 | static const object objectType; |
| 50 | 53 | ||
| 51 | static const std::list<std::string> select; | 54 | static const std::list<std::string> select; |
| 52 | 55 | ||
| 53 | // Query fields | 56 | // Query fields |
| 54 | 57 | ||
| 55 | static const field id; | 58 | static const field id; |
| 56 | 59 | ||
| 57 | operator filter() const | 60 | operator filter() const |
| 58 | { | 61 | { |
| 59 | if (!valid_) | 62 | if (!valid_) |
| 60 | { | 63 | { |
| 61 | throw std::domain_error("Bad access to uninitialized group"); | 64 | throw std::domain_error("Bad access to uninitialized group"); |
| 62 | } | 65 | } |
| 63 | 66 | ||
| 64 | return (id == id_); | 67 | return (id == id_); |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 67 | // Relationships to other objects | 70 | // Relationships to other objects |
| 68 | 71 | ||
| 69 | static const field frame; | 72 | static const field frame; |
| 70 | 73 | ||
| 71 | static const field word; | 74 | static const field word; |
| 72 | 75 | ||
| 73 | private: | 76 | private: |
| 74 | bool valid_ = false; | 77 | bool valid_ = false; |
| 75 | 78 | ||
| 76 | int id_; | 79 | int id_; |
| 77 | 80 | std::map<std::string, role> roles_; | |
| 81 | |||
| 78 | const database* db_; | 82 | const database* db_; |
| 79 | 83 | ||
| 80 | mutable bool initializedFrames_ = false; | 84 | mutable bool initializedFrames_ = false; |
| 81 | mutable std::vector<class frame> frames_; | 85 | mutable std::vector<class frame> frames_; |
| 82 | 86 | ||
| 83 | }; | 87 | }; |
| 84 | 88 | ||
| 85 | }; | 89 | }; |
| 86 | 90 | ||
| 87 | #endif /* end of include guard: GROUP_H_BD6933C0 */ | 91 | #endif /* end of include guard: GROUP_H_BD6933C0 */ |
| diff --git a/lib/part.cpp b/lib/part.cpp new file mode 100644 index 0000000..e66d151 --- /dev/null +++ b/lib/part.cpp | |||
| @@ -0,0 +1,344 @@ | |||
| 1 | #include "part.h" | ||
| 2 | #include <stdexcept> | ||
| 3 | #include "selrestr.h" | ||
| 4 | |||
| 5 | namespace verbly { | ||
| 6 | |||
| 7 | part part::createNounPhrase(std::string role, selrestr selrestrs, std::set<std::string> synrestrs) | ||
| 8 | { | ||
| 9 | part p(type::noun_phrase); | ||
| 10 | |||
| 11 | new(&p.noun_phrase_.role) std::string(std::move(role)); | ||
| 12 | new(&p.noun_phrase_.selrestrs) selrestr(std::move(selrestrs)); | ||
| 13 | new(&p.noun_phrase_.synrestrs) std::set<std::string>(std::move(synrestrs)); | ||
| 14 | |||
| 15 | return p; | ||
| 16 | } | ||
| 17 | |||
| 18 | part part::createVerb() | ||
| 19 | { | ||
| 20 | return part(type::verb); | ||
| 21 | } | ||
| 22 | |||
| 23 | part part::createPreposition(std::vector<std::string> choices, bool literal) | ||
| 24 | { | ||
| 25 | part p(type::preposition); | ||
| 26 | |||
| 27 | new(&p.preposition_.choices) std::vector<std::string>(std::move(choices)); | ||
| 28 | p.preposition_.literal = literal; | ||
| 29 | |||
| 30 | return p; | ||
| 31 | } | ||
| 32 | |||
| 33 | part part::createAdjective() | ||
| 34 | { | ||
| 35 | return part(type::adjective); | ||
| 36 | } | ||
| 37 | |||
| 38 | part part::createAdverb() | ||
| 39 | { | ||
| 40 | return part(type::adverb); | ||
| 41 | } | ||
| 42 | |||
| 43 | part part::createLiteral(std::string value) | ||
| 44 | { | ||
| 45 | part p(type::literal); | ||
| 46 | |||
| 47 | new(&p.literal_) std::string(std::move(value)); | ||
| 48 | |||
| 49 | return p; | ||
| 50 | } | ||
| 51 | |||
| 52 | part::part(const part& other) | ||
| 53 | { | ||
| 54 | type_ = other.type_; | ||
| 55 | |||
| 56 | switch (type_) | ||
| 57 | { | ||
| 58 | case type::noun_phrase: | ||
| 59 | { | ||
| 60 | new(&noun_phrase_.role) std::string(other.noun_phrase_.role); | ||
| 61 | new(&noun_phrase_.selrestrs) selrestr(other.noun_phrase_.selrestrs); | ||
| 62 | new(&noun_phrase_.synrestrs) std::set<std::string>(other.noun_phrase_.synrestrs); | ||
| 63 | |||
| 64 | break; | ||
| 65 | } | ||
| 66 | |||
| 67 | case type::preposition: | ||
| 68 | { | ||
| 69 | new(&preposition_.choices) std::vector<std::string>(other.preposition_.choices); | ||
| 70 | preposition_.literal = other.preposition_.literal; | ||
| 71 | |||
| 72 | break; | ||
| 73 | } | ||
| 74 | |||
| 75 | case type::literal: | ||
| 76 | { | ||
| 77 | new(&literal_) std::string(other.literal_); | ||
| 78 | |||
| 79 | break; | ||
| 80 | } | ||
| 81 | |||
| 82 | case type::verb: | ||
| 83 | case type::adjective: | ||
| 84 | case type::adverb: | ||
| 85 | case type::invalid: | ||
| 86 | { | ||
| 87 | break; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | part::part(part&& other) : part() | ||
| 93 | { | ||
| 94 | swap(*this, other); | ||
| 95 | } | ||
| 96 | |||
| 97 | part& part::operator=(part other) | ||
| 98 | { | ||
| 99 | swap(*this, other); | ||
| 100 | |||
| 101 | return *this; | ||
| 102 | } | ||
| 103 | |||
| 104 | void swap(part& first, part& second) | ||
| 105 | { | ||
| 106 | using type = part::type; | ||
| 107 | |||
| 108 | type tempType = first.type_; | ||
| 109 | std::string tempRole; | ||
| 110 | selrestr tempSelrestrs; | ||
| 111 | std::set<std::string> tempSynrestrs; | ||
| 112 | std::vector<std::string> tempChoices; | ||
| 113 | bool tempPrepLiteral; | ||
| 114 | std::string tempLiteralValue; | ||
| 115 | |||
| 116 | switch (tempType) | ||
| 117 | { | ||
| 118 | case type::noun_phrase: | ||
| 119 | { | ||
| 120 | tempRole = std::move(first.noun_phrase_.role); | ||
| 121 | tempSelrestrs = std::move(first.noun_phrase_.selrestrs); | ||
| 122 | tempSynrestrs = std::move(first.noun_phrase_.synrestrs); | ||
| 123 | |||
| 124 | break; | ||
| 125 | } | ||
| 126 | |||
| 127 | case type::preposition: | ||
| 128 | { | ||
| 129 | tempChoices = std::move(first.preposition_.choices); | ||
| 130 | tempPrepLiteral = first.preposition_.literal; | ||
| 131 | |||
| 132 | break; | ||
| 133 | } | ||
| 134 | |||
| 135 | case type::literal: | ||
| 136 | { | ||
| 137 | tempLiteralValue = std::move(first.literal_); | ||
| 138 | |||
| 139 | break; | ||
| 140 | } | ||
| 141 | |||
| 142 | case type::verb: | ||
| 143 | case type::adjective: | ||
| 144 | case type::adverb: | ||
| 145 | case type::invalid: | ||
| 146 | { | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | first.~part(); | ||
| 152 | |||
| 153 | first.type_ = second.type_; | ||
| 154 | |||
| 155 | switch (first.type_) | ||
| 156 | { | ||
| 157 | case type::noun_phrase: | ||
| 158 | { | ||
| 159 | new(&first.noun_phrase_.role) std::string(std::move(second.noun_phrase_.role)); | ||
| 160 | new(&first.noun_phrase_.selrestrs) selrestr(std::move(second.noun_phrase_.selrestrs)); | ||
| 161 | new(&first.noun_phrase_.synrestrs) std::set<std::string>(std::move(second.noun_phrase_.synrestrs)); | ||
| 162 | |||
| 163 | break; | ||
| 164 | } | ||
| 165 | |||
| 166 | case type::preposition: | ||
| 167 | { | ||
| 168 | new(&first.preposition_.choices) std::vector<std::string>(std::move(second.preposition_.choices)); | ||
| 169 | first.preposition_.literal = second.preposition_.literal; | ||
| 170 | |||
| 171 | break; | ||
| 172 | } | ||
| 173 | |||
| 174 | case type::literal: | ||
| 175 | { | ||
| 176 | new(&first.literal_) std::string(std::move(second.literal_)); | ||
| 177 | |||
| 178 | break; | ||
| 179 | } | ||
| 180 | |||
| 181 | case type::verb: | ||
| 182 | case type::adjective: | ||
| 183 | case type::adverb: | ||
| 184 | case type::invalid: | ||
| 185 | { | ||
| 186 | break; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | second.~part(); | ||
| 191 | |||
| 192 | second.type_ = tempType; | ||
| 193 | |||
| 194 | switch (second.type_) | ||
| 195 | { | ||
| 196 | case type::noun_phrase: | ||
| 197 | { | ||
| 198 | new(&second.noun_phrase_.role) std::string(std::move(tempRole)); | ||
| 199 | new(&second.noun_phrase_.selrestrs) selrestr(std::move(tempSelrestrs)); | ||
| 200 | new(&second.noun_phrase_.synrestrs) std::set<std::string>(std::move(tempSynrestrs)); | ||
| 201 | |||
| 202 | break; | ||
| 203 | } | ||
| 204 | |||
| 205 | case type::preposition: | ||
| 206 | { | ||
| 207 | new(&second.preposition_.choices) std::vector<std::string>(std::move(tempChoices)); | ||
| 208 | second.preposition_.literal = tempPrepLiteral; | ||
| 209 | |||
| 210 | break; | ||
| 211 | } | ||
| 212 | |||
| 213 | case type::literal: | ||
| 214 | { | ||
| 215 | new(&second.literal_) std::string(std::move(tempLiteralValue)); | ||
| 216 | |||
| 217 | break; | ||
| 218 | } | ||
| 219 | |||
| 220 | case type::verb: | ||
| 221 | case type::adjective: | ||
| 222 | case type::adverb: | ||
| 223 | case type::invalid: | ||
| 224 | { | ||
| 225 | break; | ||
| 226 | } | ||
| 227 | } | ||
| 228 | } | ||
| 229 | |||
| 230 | part::~part() | ||
| 231 | { | ||
| 232 | switch (type_) | ||
| 233 | { | ||
| 234 | case type::noun_phrase: | ||
| 235 | { | ||
| 236 | using string_type = std::string; | ||
| 237 | using set_type = std::set<std::string>; | ||
| 238 | |||
| 239 | noun_phrase_.role.~string_type(); | ||
| 240 | noun_phrase_.selrestrs.~selrestr(); | ||
| 241 | noun_phrase_.synrestrs.~set_type(); | ||
| 242 | |||
| 243 | break; | ||
| 244 | } | ||
| 245 | |||
| 246 | case type::preposition: | ||
| 247 | { | ||
| 248 | using vector_type = std::vector<std::string>; | ||
| 249 | |||
| 250 | preposition_.choices.~vector_type(); | ||
| 251 | |||
| 252 | break; | ||
| 253 | } | ||
| 254 | |||
| 255 | case type::literal: | ||
| 256 | { | ||
| 257 | using string_type = std::string; | ||
| 258 | |||
| 259 | literal_.~string_type(); | ||
| 260 | |||
| 261 | break; | ||
| 262 | } | ||
| 263 | |||
| 264 | case type::verb: | ||
| 265 | case type::adjective: | ||
| 266 | case type::adverb: | ||
| 267 | case type::invalid: | ||
| 268 | { | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | std::string part::getNounRole() const | ||
| 275 | { | ||
| 276 | if (type_ == type::noun_phrase) | ||
| 277 | { | ||
| 278 | return noun_phrase_.role; | ||
| 279 | } else { | ||
| 280 | throw std::domain_error("part::getNounRole is only valid for noun phrase parts"); | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | selrestr part::getNounSelrestrs() const | ||
| 285 | { | ||
| 286 | if (type_ == type::noun_phrase) | ||
| 287 | { | ||
| 288 | return noun_phrase_.selrestrs; | ||
| 289 | } else { | ||
| 290 | throw std::domain_error("part::getNounSelrestrs is only valid for noun phrase parts"); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | std::set<std::string> part::getNounSynrestrs() const | ||
| 295 | { | ||
| 296 | if (type_ == type::noun_phrase) | ||
| 297 | { | ||
| 298 | return noun_phrase_.synrestrs; | ||
| 299 | } else { | ||
| 300 | throw std::domain_error("part::getNounSynrestrs is only valid for noun phrase parts"); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | bool part::nounHasSynrestr(std::string synrestr) const | ||
| 305 | { | ||
| 306 | if (type_ != type::noun_phrase) | ||
| 307 | { | ||
| 308 | throw std::domain_error("part::nounHasSynrestr is only valid for noun phrase parts"); | ||
| 309 | } | ||
| 310 | |||
| 311 | return (noun_phrase_.synrestrs.count(synrestr) == 1); | ||
| 312 | } | ||
| 313 | |||
| 314 | std::vector<std::string> part::getPrepositionChoices() const | ||
| 315 | { | ||
| 316 | if (type_ == type::preposition) | ||
| 317 | { | ||
| 318 | return preposition_.choices; | ||
| 319 | } else { | ||
| 320 | throw std::domain_error("part::getPrepositionChoices is only valid for preposition parts"); | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | bool part::isPrepositionLiteral() const | ||
| 325 | { | ||
| 326 | if (type_ == type::preposition) | ||
| 327 | { | ||
| 328 | return preposition_.literal; | ||
| 329 | } else { | ||
| 330 | throw std::domain_error("part::isPrepositionLiteral is only valid for preposition parts"); | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | std::string part::getLiteralValue() const | ||
| 335 | { | ||
| 336 | if (type_ == type::literal) | ||
| 337 | { | ||
| 338 | return literal_; | ||
| 339 | } else { | ||
| 340 | throw std::domain_error("part::getLiteralValue is only valid for literal parts"); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | }; | ||
| diff --git a/lib/part.h b/lib/part.h new file mode 100644 index 0000000..3a15638 --- /dev/null +++ b/lib/part.h | |||
| @@ -0,0 +1,117 @@ | |||
| 1 | #ifndef PART_H_C8F0661B | ||
| 2 | #define PART_H_C8F0661B | ||
| 3 | |||
| 4 | #include <string> | ||
| 5 | #include <vector> | ||
| 6 | #include <set> | ||
| 7 | #include "selrestr.h" | ||
| 8 | |||
| 9 | namespace verbly { | ||
| 10 | |||
| 11 | class part { | ||
| 12 | public: | ||
| 13 | enum class type { | ||
| 14 | invalid = -1, | ||
| 15 | noun_phrase = 0, | ||
| 16 | verb = 1, | ||
| 17 | preposition = 2, | ||
| 18 | adjective = 3, | ||
| 19 | adverb = 4, | ||
| 20 | literal = 5 | ||
| 21 | }; | ||
| 22 | |||
| 23 | // Static factories | ||
| 24 | |||
| 25 | static part createNounPhrase(std::string role, selrestr selrestrs, std::set<std::string> synrestrs); | ||
| 26 | |||
| 27 | static part createVerb(); | ||
| 28 | |||
| 29 | static part createPreposition(std::vector<std::string> choices, bool literal); | ||
| 30 | |||
| 31 | static part createAdjective(); | ||
| 32 | |||
| 33 | static part createAdverb(); | ||
| 34 | |||
| 35 | static part createLiteral(std::string value); | ||
| 36 | |||
| 37 | // Default constructor | ||
| 38 | |||
| 39 | part() | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | // Copy and move constructors | ||
| 44 | |||
| 45 | part(const part& other); | ||
| 46 | |||
| 47 | part(part&& other); | ||
| 48 | |||
| 49 | // Assignment | ||
| 50 | |||
| 51 | part& operator=(part other); | ||
| 52 | |||
| 53 | // Swap | ||
| 54 | |||
| 55 | friend void swap(part& first, part& second); | ||
| 56 | |||
| 57 | // Destructor | ||
| 58 | |||
| 59 | ~part(); | ||
| 60 | |||
| 61 | // General accessors | ||
| 62 | |||
| 63 | type getType() const | ||
| 64 | { | ||
| 65 | return type_; | ||
| 66 | } | ||
| 67 | |||
| 68 | // Noun phrase accessors | ||
| 69 | |||
| 70 | std::string getNounRole() const; | ||
| 71 | |||
| 72 | selrestr getNounSelrestrs() const; | ||
| 73 | |||
| 74 | std::set<std::string> getNounSynrestrs() const; | ||
| 75 | |||
| 76 | bool nounHasSynrestr(std::string synrestr) const; | ||
| 77 | |||
| 78 | // Preposition accessors | ||
| 79 | |||
| 80 | std::vector<std::string> getPrepositionChoices() const; | ||
| 81 | |||
| 82 | bool isPrepositionLiteral() const; | ||
| 83 | |||
| 84 | // Literal accessors | ||
| 85 | |||
| 86 | std::string getLiteralValue() const; | ||
| 87 | |||
| 88 | private: | ||
| 89 | |||
| 90 | // Private constructors | ||
| 91 | |||
| 92 | part(type t) : type_(t) | ||
| 93 | { | ||
| 94 | } | ||
| 95 | |||
| 96 | // Data | ||
| 97 | |||
| 98 | union { | ||
| 99 | struct { | ||
| 100 | std::string role; | ||
| 101 | selrestr selrestrs; | ||
| 102 | std::set<std::string> synrestrs; | ||
| 103 | } noun_phrase_; | ||
| 104 | struct { | ||
| 105 | std::vector<std::string> choices; | ||
| 106 | bool literal; | ||
| 107 | } preposition_; | ||
| 108 | std::string literal_; | ||
| 109 | }; | ||
| 110 | |||
| 111 | type type_ = type::invalid; | ||
| 112 | |||
| 113 | }; | ||
| 114 | |||
| 115 | }; | ||
| 116 | |||
| 117 | #endif /* end of include guard: PART_H_C8F0661B */ | ||
