Commit ·
1df04f3
1
Parent(s): a18eebf
Upload 2 files
Browse files- ChatIPC.cpp +110 -2
ChatIPC.cpp
CHANGED
|
@@ -16,6 +16,7 @@
|
|
| 16 |
#include <unordered_map>
|
| 17 |
#include <unordered_set>
|
| 18 |
#include <vector>
|
|
|
|
| 19 |
|
| 20 |
#ifdef _OPENMP
|
| 21 |
#include <omp.h>
|
|
@@ -308,13 +309,108 @@ static std::vector<std::string> tokenize_whitespace(const std::string &s){
|
|
| 308 |
return out;
|
| 309 |
}
|
| 310 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 311 |
static std::vector<std::string> tokenize_others(const std::string &s) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 312 |
std::vector<std::string> out;
|
| 313 |
std::string cur;
|
| 314 |
|
|
|
|
| 315 |
auto flush = [&]() {
|
| 316 |
if (!cur.empty()) {
|
| 317 |
-
|
|
|
|
|
|
|
|
|
|
| 318 |
cur.clear();
|
| 319 |
}
|
| 320 |
};
|
|
@@ -323,6 +419,7 @@ static std::vector<std::string> tokenize_others(const std::string &s) {
|
|
| 323 |
unsigned char uc = static_cast<unsigned char>(s[i]);
|
| 324 |
char ch = static_cast<char>(uc);
|
| 325 |
|
|
|
|
| 326 |
if (ch == '_' || ch == '-' || ch == '/' || std::isspace(uc)) {
|
| 327 |
flush();
|
| 328 |
continue;
|
|
@@ -341,7 +438,18 @@ static std::vector<std::string> tokenize_others(const std::string &s) {
|
|
| 341 |
camel_boundary = prev_lower_or_digit || (prev_upper && next_lower);
|
| 342 |
}
|
| 343 |
|
| 344 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 345 |
flush();
|
| 346 |
}
|
| 347 |
|
|
|
|
| 16 |
#include <unordered_map>
|
| 17 |
#include <unordered_set>
|
| 18 |
#include <vector>
|
| 19 |
+
#include <string>
|
| 20 |
|
| 21 |
#ifdef _OPENMP
|
| 22 |
#include <omp.h>
|
|
|
|
| 309 |
return out;
|
| 310 |
}
|
| 311 |
|
| 312 |
+
// Static helper to check dictionary presence using your existing pos cache
|
| 313 |
+
static inline bool check_dictionary(const std::string &word) {
|
| 314 |
+
return !dictionary_pos_for_token(word).empty();
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
// Morphological lemmatizer to convert sub-tokens to their dictionary-defined base form.
|
| 318 |
+
// Returns std::optional<std::string>: contains the valid base form if found in the dictionary,
|
| 319 |
+
// or std::nullopt if the token has no definition and should be ignored.
|
| 320 |
+
static std::optional<std::string> get_valid_base_form(const std::string &word) {
|
| 321 |
+
if (word.empty()) return std::nullopt;
|
| 322 |
+
|
| 323 |
+
// 1. BEFORE extracting/stemming, check if the original form is already in the dictionary
|
| 324 |
+
if (check_dictionary(word)) {
|
| 325 |
+
return word;
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
// 2. Continuous verb form (-ing)
|
| 329 |
+
if (word.length() > 3 && word.substr(word.length() - 3) == "ing") {
|
| 330 |
+
// e.g., playing -> play
|
| 331 |
+
std::string base1 = word.substr(0, word.length() - 3);
|
| 332 |
+
if (check_dictionary(base1)) return base1;
|
| 333 |
+
|
| 334 |
+
// e.g., making -> make
|
| 335 |
+
std::string base2 = base1 + "e";
|
| 336 |
+
if (check_dictionary(base2)) return base2;
|
| 337 |
+
|
| 338 |
+
// e.g., running -> run (doubled consonant check)
|
| 339 |
+
if (base1.length() >= 2 && base1.back() == base1[base1.length() - 2]) {
|
| 340 |
+
std::string base3 = base1.substr(0, base1.length() - 1);
|
| 341 |
+
if (check_dictionary(base3)) return base3;
|
| 342 |
+
}
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
// 3. Past tense / Participle form (-ed)
|
| 346 |
+
if (word.length() > 2 && word.substr(word.length() - 2) == "ed") {
|
| 347 |
+
// e.g., baked -> bake
|
| 348 |
+
std::string base1 = word.substr(0, word.length() - 1);
|
| 349 |
+
if (check_dictionary(base1)) return base1;
|
| 350 |
+
|
| 351 |
+
// e.g., played -> play
|
| 352 |
+
std::string base2 = word.substr(0, word.length() - 2);
|
| 353 |
+
if (check_dictionary(base2)) return base2;
|
| 354 |
+
|
| 355 |
+
// e.g., hopped -> hop (doubled consonant check)
|
| 356 |
+
if (base2.length() >= 2 && base2.back() == base2[base2.length() - 2]) {
|
| 357 |
+
std::string base3 = base2.substr(0, base2.length() - 1);
|
| 358 |
+
if (check_dictionary(base3)) return base3;
|
| 359 |
+
}
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
// 4. Plural / 3rd-person singular form (-ies -> -y)
|
| 363 |
+
if (word.length() > 3 && word.substr(word.length() - 3) == "ies") {
|
| 364 |
+
std::string base = word.substr(0, word.length() - 3) + "y";
|
| 365 |
+
if (check_dictionary(base)) return base;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
// 5. Plural / 3rd-person singular form (-ves -> -f / -fe)
|
| 369 |
+
if (word.length() > 3 && word.substr(word.length() - 3) == "ves") {
|
| 370 |
+
std::string base1 = word.substr(0, word.length() - 3) + "f";
|
| 371 |
+
if (check_dictionary(base1)) return base1;
|
| 372 |
+
|
| 373 |
+
std::string base2 = word.substr(0, word.length() - 3) + "fe";
|
| 374 |
+
if (check_dictionary(base2)) return base2;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
// 6. Plural form (-es)
|
| 378 |
+
if (word.length() > 2 && word.substr(word.length() - 2) == "es") {
|
| 379 |
+
std::string base = word.substr(0, word.length() - 2);
|
| 380 |
+
if (check_dictionary(base)) return base;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
// 7. Plural form (-s)
|
| 384 |
+
if (word.length() > 1 && word.back() == 's' && word[word.length() - 2] != 's') {
|
| 385 |
+
std::string base = word.substr(0, word.length() - 1);
|
| 386 |
+
if (check_dictionary(base)) return base;
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
// No dictionary-defined base form found
|
| 390 |
+
return std::nullopt;
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
static std::vector<std::string> tokenize_others(const std::string &s) {
|
| 394 |
+
// Step A: Check if the entire input string already has a dictionary definition.
|
| 395 |
+
if (check_dictionary(s)) {
|
| 396 |
+
std::string lower_s;
|
| 397 |
+
lower_s.reserve(s.size());
|
| 398 |
+
for (char c : s) {
|
| 399 |
+
lower_s.push_back(to_low(c));
|
| 400 |
+
}
|
| 401 |
+
return { lower_s };
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
std::vector<std::string> out;
|
| 405 |
std::string cur;
|
| 406 |
|
| 407 |
+
// Lambda to flush the accumulated token buffer, validate it, and add to output
|
| 408 |
auto flush = [&]() {
|
| 409 |
if (!cur.empty()) {
|
| 410 |
+
auto valid_base = get_valid_base_form(cur);
|
| 411 |
+
if (valid_base.has_value()) {
|
| 412 |
+
out.push_back(valid_base.value());
|
| 413 |
+
}
|
| 414 |
cur.clear();
|
| 415 |
}
|
| 416 |
};
|
|
|
|
| 419 |
unsigned char uc = static_cast<unsigned char>(s[i]);
|
| 420 |
char ch = static_cast<char>(uc);
|
| 421 |
|
| 422 |
+
// Split on spaces, underscores, hyphens, and slashes
|
| 423 |
if (ch == '_' || ch == '-' || ch == '/' || std::isspace(uc)) {
|
| 424 |
flush();
|
| 425 |
continue;
|
|
|
|
| 438 |
camel_boundary = prev_lower_or_digit || (prev_upper && next_lower);
|
| 439 |
}
|
| 440 |
|
| 441 |
+
// Split on transitions between alphabetical characters and digits (e.g., "book5read")
|
| 442 |
+
bool digit_boundary = false;
|
| 443 |
+
if (!cur.empty()) {
|
| 444 |
+
unsigned char prev = static_cast<unsigned char>(s[i - 1]);
|
| 445 |
+
bool prev_digit = std::isdigit(prev) != 0;
|
| 446 |
+
bool curr_digit = std::isdigit(uc) != 0;
|
| 447 |
+
if (prev_digit != curr_digit) {
|
| 448 |
+
digit_boundary = true;
|
| 449 |
+
}
|
| 450 |
+
}
|
| 451 |
+
|
| 452 |
+
if (camel_boundary || digit_boundary) {
|
| 453 |
flush();
|
| 454 |
}
|
| 455 |
|