void Solarix::PrintTags( SG_TagsList tags, lem::UFString &str, SynGram &sg ) { str.clear(); if( tags!=NULL ) { for( lem::Container::size_type i=0; i<tags->size(); ++i ) { const int itag = (*tags)[i].first; const int ival = (*tags)[i].second; const ThesaurusTag &tag = sg.Get_Net().GetTagDefs()[itag]; if( !str.empty() ) str += L' '; str += tag.GetName().c_str(); if( ival!=UNKNOWN ) { const lem::UCString &val = tag[ival]; str += L'='; str += val.c_str(); } } } return; }
WordFormEnumeratorGlobbing_File::WordFormEnumeratorGlobbing_File( WordEntries_File * _entries, const lem::UFString &_mask ) : WordFormEnumeratorListing_File(_entries), mask(_mask) { LEM_CHECKIT_Z(!_mask.empty()); return; }
SG_DeclensionForm::SG_DeclensionForm( const lem::UFString & lexem_generator, const lem::UFString & rx_condition, const lem::UFString & rx_flexer_flags, const CP_Array & dims ) : dim(dims), form(lexem_generator.c_str()) { valid_condition = !rx_condition.empty(); valid_flexer_flags = !rx_flexer_flags.empty(); condition_str = rx_condition; flexer_flags_str = rx_flexer_flags; if( !condition_str.empty() ) condition = boost::wregex( condition_str.c_str(), boost::basic_regex<wchar_t>::icase ); if( !flexer_flags.empty() ) flexer_flags = boost::wregex( flexer_flags_str.c_str(), boost::basic_regex<wchar_t>::icase ); return; }
bool SyntaxShell::TryCommand( const lem::UFString &_str ) { LEM_CHECKIT_Z( !_str.empty() ); if( _str==L"#help" || _str==L"?" ) { ShowHelp(); return true; } if( _str.front()!=L'#' ) return false; if( _str.eq_beg( L"# " ) ) return true; // комментарий if( _str.eq_beg( L"#timeout" ) ) { lem::MCollect<UCString> toks; lem::parse( _str, toks, false ); MaxTimeout = lem::to_int( toks[1] ); return true; } if( _str.eq_beg( L"#maxalt" ) ) { lem::MCollect<UCString> toks; lem::parse( _str, toks, false ); MaxAlt = lem::to_int( toks[1] ); lem::mout->printf( "MaxAlt=%d\n", MaxAlt ); return true; } if( _str.eq_beg( L"#maxskiptoken" ) ) { lem::MCollect<UCString> toks; lem::parse( _str, toks, false ); MaxSkipToken = lem::to_int( toks[1] ); lem::mout->printf( "MaxSkipToken=%d\n", MaxSkipToken ); if( MaxSkipToken>0 ) CompleteAnalysisOnly = false; if( MaxAlt==0 || MaxAlt==lem::int_max ) { lem::mout->printf( "Attention: it is highly recommended to use %vfE#maxalt%vn NNN in order to limit the search tree depth\n" ); } return true; } if( _str.eq_beg( L"#sem" ) ) { lem::MCollect<UCString> toks; lem::parse( _str, toks, false ); FindFacts = lem::to_bool( toks[1] ); return true; } if( _str.eqi( L"#info" ) ) { ShowDictionaryInfo(); return true; } if( _str.eqi( L"#disconnect" ) ) { sol_id.Delete(); lem::mout->printf( "Dictionary database is disconnected.\n" ); return true; } if( _str.eqi( L"#connect" ) ) { LoadDictionary(); return true; } if( _str.eq_begi( L"#tag" ) ) { if( _str==L"#tag-" ) { // Сбрасываем установленный фильтр tags_ptr.Delete(); tags.clear(); return true; } lem::Collect<lem::UFString> toks; lem::parse( UFString(_str.c_str()+4), toks, L"=" ); UCString tag_name, tag_value; if( toks.size()>0 ) tag_name = toks[0].c_str(); if( toks.size()>1 ) tag_value = toks[1].c_str(); tag_name.trim(); tag_value.trim(); const int itag = sol_id->GetSynGram().Get_Net().FindTag(tag_name); if( itag==UNKNOWN ) { lem::mout->printf( "Tag [%vfE%us%vn] not found\n", tag_name.c_str() ); return true; } const ThesaurusTag &tt = sol_id->GetSynGram().Get_Net().GetTagDefs()[itag]; if( tt.CountValues()>0 ) { int ivalue = tt[tag_value]; if( ivalue==UNKNOWN ) { lem::mout->printf( "Tag value [%vfE%us%vn] not found\n", tag_value.c_str() ); return true; } } tags_ptr = new TF_TagOrNullFilter( *sol_id, tag_name, tag_value ); return true; } if( _str.eq_begi( L"#param" ) ) { if( _str==L"#param-" ) { // Очищаем список параметров. params.clear(); return true; } lem::Collect<lem::UFString> toks; lem::parse( UFString(_str.c_str()+7), toks, L"=" ); UCString param_name, param_value; if( toks.size()>0 ) param_name = toks[0].c_str(); if( toks.size()>1 ) param_value = toks[1].c_str(); param_name.trim(); param_value.trim(); params.push_back( std::make_pair( param_name, param_value ) ); return true; } lem::UFString str = lem::right( _str, _str.length()-1 ); lem::zbool ret; if( str==L"debug" ) { SetDebug(true); ret=true; } else if( str==L"nodebug" ) { SetDebug(false); ret=true; } else if( str==L"traceon" ) { SetDebug(true); traceon=true; debugger->Trace(true); ret=true; } else if( str==L"traceoff" ) { traceon=false; if( debugger.NotNull() ) debugger->Trace(true); ret=true; } else if( str==L"fuzzyon" ) { allow_fuzzy = true; mout->printf( "Fuzzy projection is now %vfAON%vn\n" ); ret=true; } else if( str==L"fuzzyoff" ) { allow_fuzzy = false; mout->printf( "Fuzzy projection is now %vfDOFF%vn\n" ); ret=true; } else if( str=="disable_filters" ) { EnableFilters=false; ret = true; } else if( str=="enable_filters" ) { EnableFilters=true; ret = true; } else if( str=="schedule1" ) { CompleteAnalysisOnly=true; UseTopDownThenSparse=true; mout->printf( "Workflow=%vfATOP-DOWN, TOP-DOWN INCOMPLETE%vn\n" ); ret=true; } else if( str==L"topdown" ) { UseTopDownThenSparse=false; CompleteAnalysisOnly=true; mout->printf( "%vfAtop-down%vn analyzer is activated\n" ); ret=true; } else if( str==L"allow_incomplete" ) { CompleteAnalysisOnly = false; mout->printf( "Incomplete analysis is %vfAALLOWED%vn\n" ); ret=true; } else if( str==L"disallow_incomplete" ) { CompleteAnalysisOnly = true; mout->printf( "Incomplete analysis is %vfDDISALLOWED%vn\n" ); ret=true; } else if( str==L"allow_reco" ) { UseReconstructor = true; mout->printf( "Token reconstructor is %vfAALLOWED%vn\n" ); ret=true; } else if( str==L"disallow_reco" ) { UseReconstructor = false; mout->printf( "Token reconstructor is %vfDDISALLOWED%vn\n" ); ret=true; } else if( str==L"allow_model" ) { if( sol_id->GetLexAuto().GetModel().GetSequenceLabeler().IsAvailable() || sol_id->GetLexAuto().GetModel().GetClassifier().IsAvailable() ) { ApplyModel = true; mout->printf( "Morphology model is enabled\n" ); } else { mout->printf( "Morphology model is not available\n" ); } ret=true; } else if( str==L"disallow_model" ) { ApplyModel = false; mout->printf( "Morphology model is disabled\n" ); ret=true; } else if( str==L"show" ) { if( current_analysis.NotNull() ) { const Res_Pack &pack = current_analysis->GetPack(); mout->printf( "\nResult pack contains %vfE%d%vn variators:\n", pack.vars().size() ); if( run_mode==MorphologyMode ) { for( lem::Container::size_type i=0; i<pack.vars().size(); i++ ) { const Variator * var = pack.vars()[i]; for( lem::Container::size_type k=0; k<var->size(); ++k ) { const Tree_Node & root = var->get(k); mout->printf( "%d: ", CastSizeToInt(k) ); root.Print( *lem::mout, sol_id->GetSynGram(), -1, true ); mout->eol(); } mout->eol(); mout->eol(); } } else { for( lem::Container::size_type i=0; i<pack.vars().size(); i++ ) { pack.vars()[i]->PrintV( *mout, sol_id->GetSynGram(), true ); mout->eol(); mout->eol(); } } } ret=true; } else if( str==L"tree" ) { if( current_analysis.NotNull() ) { const Res_Pack &pack = current_analysis->GetPack(); Solarix::print_syntax_tree( current_analysis->GetString(), current_analysis->GetPack(), *sol_id, *lem::mout, false, true ); } ret=true; } else if( str.eq_beg("recog" ) ) { if( current_analysis.NotNull() ) { lem::mout->eol(); current_analysis->GetLexer().PrintRecognitions( *lem::mout ); } return true; } else if( str==L"tokenize" ) { SetMode(TokenizerMode); ret=true; } else if( str==L"lemmatize" ) { SetMode(LemmatizerMode); ret=true; } else if( str==L"speak" ) { SetMode(SpeakerMode); ret=true; } else if( str==L"syntax" ) { SetMode(SyntaxMode); ret=true; } else if( str==L"morphology" ) { SetMode(MorphologyMode); ret=true; } else if( str==L"debugger" ) { if( debugger.NotNull() ) debugger->ManageBreakpoints(); ret=true; } else { lem::mout->printf( "Invalid command %vfC%us%vn\n", str.c_str() ); ret=true; } return ret; }
bool SentenceBroker::Fetch(lem::UFString &line, int & line_paragraph_id) { line.clear(); line_paragraph_id = cur_paragraph_id; if (eof) return false; int n_quote = 0; // для учета символов " // Пропустим начальные пробелы. while (!eof) { wchar_t c = GetChar(); if (c == WEOF) { break; } if (!lem::is_uspace(c) || IsEndOfSentenceMarker(c)) { UngetChar(c); break; } } while (!eof || !chars.empty()) { wchar_t c = GetChar(); if (c == WEOF) { eof = true; return true; } else if (c == L' ') { line += c; continue; } else if (IsEndOfSentenceMarker(c)) { line += c; break; } bool line_ready = false; if ( (line.empty() || IsTokenDelimiter(line.back()) || IsTokenDelimiter(c)) && tokenizer.NotNull() && tokenizer->IsUnbreakableFront(c) ) { // Возможно далее идет исключительный случай. Выбираем символы из входного потока в // попытке сконструировать максимально длинное исключение. lem::UCString substr; substr = c; while (!eof) { wchar_t c2 = GetChar(); if (c2 == WEOF) { // Достигли конца файла. Считали полный исключительный случай? if (tokenizer->IsMatched(substr)) { // Да! line += substr.c_str(); c = c2; // Считанный токен является разделителем предложений (типа ...) if (sent_delims.find(substr) != UNKNOWN) { line.trim(); if (!line.empty() && (n_quote % 2) == 0) { count++; return true; } } } else { // нет - вернем накопленные символы в поток чтения for (int k = substr.length() - 1; k >= 0; --k) UngetChar(substr[k]); c = GetChar(); } break; } substr += c2; // добавили еще один символ. // С символов substr начинается хоть одно исключение? if (!tokenizer->IsUnbreakableFront(substr) || substr.length() == lem::UCString::max_len) { // Нет. // Возможно, предыдущая подстрока является исключительной ситуацией. UCString substr1 = lem::left(substr, substr.length() - 1); if (tokenizer->IsMatched(substr1) && IsTokenDelimiter(substr.back())) { // Да! line += substr1.c_str(); // Считанный токен является разделителем предложений (типа ...) if (sent_delims.find(substr1) != UNKNOWN) { if ((n_quote % 2) == 0) { line.trim(); if (!line.empty()) { UngetChar(c2); count++; return true; } } else { if (c2 == L'"') { // Ситуация типа Кошка говорит "Мяу!" Собака говорит "Гав!" bool continuation_found = true; lem::MCollect<wchar_t> tmp_chars; while (!eof || !chars.empty()) { const wchar_t c4 = GetChar(); tmp_chars.push_back(c4); if (!lem::is_uspace(c4)) { if (IsUpperChar(c4)) { continuation_found = false; } break; } } for (int k = CastSizeToInt(tmp_chars.size()) - 1; k >= 0; --k) UngetChar(tmp_chars[k]); if (!continuation_found) { line += c2; return true; } } } } #if defined SOL_CAA // Если считанный токен делит предложения в случае, когда за ним // идет слово с первой заглавной буквой. if (use_lexicon && casing_sent_delim.find(to_lower(substr1)) != UNKNOWN && CharCasingCoord != UNKNOWN && LowerCasingState != UNKNOWN) { Lexem next_token = PickNextToken(); if (IsUpperChar(next_token.front())) { la->TranslateLexem(next_token); int ie = UNKNOWN; if (seeker != NULL) { ie = seeker->Find(next_token, false); } else { MCollect<Word_Coord> found_list; la->ProjectWord(next_token, found_list, LanguageID); if (!found_list.empty()) ie = found_list.front().GetEntry(); } if (ie != UNKNOWN) { const Solarix::SG_Entry &e = sg->GetEntry(ie); const int casing = e.attrs().FindOnce(Solarix::GramCoordAdr(CharCasingCoord)); if (casing == LowerCasingState || casing == UNKNOWN) { UngetChar(c2); count++; return true; } } } } #endif c = c2; } else { // Возвращаем все загруженные символы обратно в поток. for (int k = substr.length() - 1; k >= 0; --k) UngetChar(substr[k]); c = GetChar(); } break; } } } if (c == WEOF) { // закончился исходный текст, принудительно прерываем текущее предложение. eof = true; return true; } const bool ItIsSentDelim = sent_delims1.find(c) != UNKNOWN; if (ItIsSentDelim) { if (IsEndOfSentenceMarker(c)) break; // Обычный конец предложения. Для точки надо проверять, если сразу после точки идет цифра // или символ в нижнем регистре, то это НЕ конец предложения. bool breaker = false; bool add_char = true; // Если у нас есть незакрытая пара ", то проверим следующий непустой символ. if ((n_quote % 2) != 0) { const wchar_t c2 = GetChar(); // Если это закрывающая " if (c2 == L'"') { n_quote++; line += c; line += c2; const wchar_t c4 = GetChar(); if (sent_delims1.find(c4) != UNKNOWN) { line += c4; count++; return true; } else { UngetChar(c4); } // если дальше - пробел, и после него идет символ в нижнем регистре, то это не конец предложения. bool continuation_found = true; UFString tmp_chars; while (!eof) { const wchar_t c5 = GetChar(); if (c5 == WEOF) { break; } tmp_chars += c5; if (!lem::is_uspace(c5)) { // найден не-пробельный символ. if (IsUpperChar(c5)) { continuation_found = false; } break; } } // возвращаем все символы обратно for (int i = CastSizeToInt(tmp_chars.size()) - 1; i >= 0; --i) UngetChar(tmp_chars[i]); if (!continuation_found) { // обрываем предложение. line.trim(); count++; return true; } } else { // нет - продолжим считывание символов предложения. line += c; line += c2; } } else { #if defined SOL_CAA if (tokenizer.NotNull() && seeker.NotNull() && use_lexicon && c == L'.') { // надо выделить слово, предшествующее точке. идем влево до разделителя токенов. int icur = line.length() - 1; while (icur >= 0) { if (tokenizer->IsTokenDelimiter(line[icur])) break; // нашли начало последнего слова else icur--; // сдвигаемся влево } Solarix::Lexem last_word; for (int j = icur + 1; j < line.length(); ++j) last_word.Add_Dirty(line[j]); last_word.calc_hash(); la->TranslateLexem(last_word); if (seeker->Find(last_word, false) != UNKNOWN) { breaker = true; } } #endif if (!breaker) { breaker = true; wchar_t c2 = PeekChar(); if (c == L'.') { if (lem::is_udigit(c2)) { breaker = false; } else if (IsLowerChar(c2)) { breaker = false; } else if (c2 == L',') { breaker = false; } else if (lem::is_uspace(c2)) { // Дойдем до первого не-пробельного символа. line += c; add_char = false; while (c != WEOF) { c = GetChar(); line += c; if (IsEndOfSentenceMarker(c)) break; c = PeekChar(); if (!lem::is_uspace(c)) { if (IsLowerChar(c)) { breaker = false; } break; } } c = L'.'; } wchar_t c0 = c; c2 = PeekChar(); if (c2 == c0) { line += c; add_char = false; while (c != WEOF && c == c0) { c = GetChar(); line += c; c = PeekChar(); } } } else if (c == '!' || c == '?') { wchar_t c0 = c; c2 = PeekChar(); if (c2 == L'?' || c2 == L'!') // То есть токены типа !!! и !? { line += c; add_char = false; while (c != WEOF && (c == L'!' || c == L'?')) { c = GetChar(); line += c; c = PeekChar(); } } } } if (c == WEOF) { eof = true; add_char = false; } if (breaker) { line_ready = true; } if (add_char) line += c; } } else if (line.length() > max_sentence_length && (lem::is_uspace(c) || c == L',' || c == L'-' || c == L';' || c == L':')) { // Слишком длинные предложения обрываем на безопасных символах. line_ready = true; line += c; } else if (c == L'\r' || c == L'\n' || c == L'\t' || c == L'\b') { // некоторые управляющие символы заменяем пробелами line += L' '; } else { line += c; if (c == L'"') n_quote++; else if (c == L'(') { // если предложение начинается с (, то надо смотреть, какой токен будет перед ), и если это терминатор - обрывать предложение. if (line.size() == 1) { if (ReadCharsUntilClosingParen(line)) { line.trim(); return true; } } else { ReadCharsUntilClosingParen(line); } } } if (line_ready) { if (line.length() > 0 && IsEndOfParagraphMarker(line.last_char())) { line.remove(line.length() - 1); cur_paragraph_id++; } line.trim(); if (!line.empty()) count++; return true; } } if (line.length() > 0 && IsEndOfParagraphMarker(line.last_char())) { line.remove(line.length() - 1); cur_paragraph_id++; } line.trim(); if (!line.empty()) count++; return true; }
void SG_ComplexLink::LoadPoint( Macro_Parser &txtfile, SynGram &gram, lem::UFString &entry ) { BethToken t = txtfile.read(); if( t.GetToken()==B_ENTRY ) { // Особый формат entry Класс:Статья { уточнение } // преобразуется в ключ статьи и возвращается в виде #ключ UCString class0 = txtfile.read().string(); const int ic0 = class0==L"?" ? ANY_STATE : gram.FindClass(class0); if( ic0==UNKNOWN ) { Print_Error( txtfile ); gram.GetIO().merr().printf( "Unknown class %us\n", class0.c_str() ); throw E_BaseException(); } txtfile.read_it( B_COLON ); UCString entry0 = sol_read_multyname( gram.GetIO(), txtfile, B_OFIGPAREN ); entry0.strip(L'"'); entry0.trim(); // Может быть задана дополнительная фильтрующая координата Solarix::CP_Array coords0; coords0.LoadTxt( txtfile, gram ); if( gram.IsOmonym(ic0,lem::to_upper(entry0)) && coords0.empty() ) { Print_Error( txtfile ); gram.GetIO().merr().printf( "Omonym %us:%us requires the coordinate array\n", class0.c_str(), entry0.c_str() ); throw E_BaseException(); } const int ie0 = coords0.empty() ? gram.FindEntry(entry0,ic0,false) : gram.FindEntryOmonym(entry0,ic0,coords0); if( ie0==UNKNOWN ) { Print_Error( txtfile ); gram.GetIO().merr().printf( "Unknown entry %us:%us\n", class0.c_str(), entry0.c_str() ); throw E_BaseException(); } const int ekey = gram.GetEntry(ie0).GetKey(); entry = lem::format_str( L"#%d", ekey ); return; } bool figparen = t.GetToken()==B_OFIGPAREN; if( !figparen ) txtfile.seekp(t); entry.reserve(128); if( t.string()==L'@' ) { entry = L'@'; t = txtfile.read(); } while( !txtfile.eof() ) { BethToken t = txtfile.read(); if( figparen && t.GetToken()==B_CFIGPAREN ) break; if( !entry.empty() ) entry.Add_Dirty(L' '); UFString ts( t.GetFullStr() ); ts.strip(L'"'); entry.Add_Dirty( ts ); if( !figparen ) break; } entry.calc_hash(); if( entry.front()==L'@' ) { // Спецсимвол @ заставляет запомнить строку в виде "как есть" entry.remove(0); entry.trim(); } else { entry.strip(L'"'); gram.GetDict().GetLexAuto().TranslateLexem(entry,true); } return; }