void BinaryFile::OpenDiskFile( const char *amode, const wchar_t *umode, bool do_throw ) { if( lem::System_Config::SupportUnicodeFilenames() ) { #if defined LEM_WINDOWS const UFString n = GetName().GetUnicode(); // У стандартной CRT Borland CBuilder 6.0 проблема - не может // открыть файл "nul" через UNICODE-функцию. if( n==L"nul" ) file=/*std::*/::fopen( "nul", amode ); else #if defined LEM_BORLAND file=/*std::*/::fopen( GetName().GetAscii().c_str(), amode ); #else file=_wfopen( n.c_str(), umode ); #endif #elif defined LEM_UNIX // перекодируем в utf-8 if( GetName().IsAscii() ) { file=::fopen( GetName().GetAscii().c_str(), amode ); } else { file=::fopen( lem::to_utf8(GetName().GetUnicode()).c_str(), amode ); } #endif } else { file=/*std::*/::fopen( GetName().GetAscii().c_str(), amode ); } if( file==NULL ) { if( do_throw ) { //printf( "File error: %s\n", filename.Get_Ascii().c_str() ); lem::UFString fn( GetName().GetUnicode() ); throw E_BaseException( wstring( L"File open error: " )+fn.c_str() ); } } #if LEM_DEBUGGING==1 n_opened++; #endif // check_file(file,filename); closable=true; IFDEBUG(Assert()); return; }
const UFString SyntaxShell::enter_cmd( const char *Prompt ) const { UFString str; while( str.empty() ) { mout->printf( "%vfF%s", Prompt ); // Command prompt str = mkey->ask_ufstring(); mout->printf( "%vn" ); str.trim(); } return str; }
const FString lem::to_ascii( const UFString &str, const CodeConverter *_cp ) { if( str.empty() ) return FString(); const CodeConverter *cp = _cp ? _cp : &lem::UI::get_UI().GetSessionCp(); const int l = str.length(); char *ascii = FString::Alloc( cp->EstimateAsciiLen(l+1) ); cp->to_ascii( str.c_str(), ascii ); return FString(ascii,true); }
void Parser::Split_Path( const UFString &path, Collect<UFString> &steps ) { int i=0; UFString new_step; while( true ) { if( path[i] == L'.' || path[i]==0 ) { if( !new_step.empty() ) steps.push_back(new_step); new_step.clear(); if( i>=path.length() ) break; } else { new_step += path[i]; } i++; } return; }
void SG_DeclensionForm::ReadAdditionalInfo( Grammar &gram, const SG_DeclensionTable &table, Macro_Parser& txtfile ) { // :: flexer рег_выражение for регулярное_выражение while( !txtfile.eof() ) { BethToken t = txtfile.read(); if( t==B_FOR ) { UFString re = strip_quotes( txtfile.read().string() ).c_str(); if( table.GetClass()!=UNKNOWN ) { const SG_Class &cls = (const SG_Class&)gram.classes()[ table.GetClass() ]; const int id_lang = cls.GetLanguage(); if( id_lang!=UNKNOWN ) { const SG_Language &lang = gram.GetDict().GetSynGram().languages()[id_lang]; lang.SubstParadigmPattern(re); } } condition_str = re; condition = boost::wregex( re.c_str(), boost::basic_regex<wchar_t>::icase ); valid_condition = true; } else if( t==B_FLEXER ) { UFString re = strip_quotes( txtfile.read().string() ).c_str(); flexer_flags_str = re; flexer_flags = boost::wregex( re.c_str(), boost::basic_regex<wchar_t>::icase ); valid_flexer_flags = true; } else { txtfile.seekp(t); break; } } return; }
// ********************************************************************* // Возвращает следующий полный токен из входного потока, не перемещая // курсор чтения. // ********************************************************************* lem::UCString SentenceBroker::PickNextToken(void) { UFString buffer; UCString res; // Сначала пропустим пробелы while (true) { const wchar_t c = GetChar(); if (c == WEOF) break; buffer += c; if (!lem::is_uspace(c)) { res = c; break; } } // Теперь считываем символы до любого разделителя while (true) { const wchar_t c = GetChar(); if (c == WEOF) break; buffer += c; if (tokenizer->IsTokenDelimiter(c)) break; res += c; } // Возвращаем обратно все считанные символы. for (int i = buffer.length() - 1; i >= 0; --i) UngetChar(buffer[i]); return res; }
static bool IsTextDelimiterTag( const UFString &tag ) { if( tags2.empty() ) { const wchar_t* stags[] = { L"p", L"br", L"table", L"td", L"tr", L"th", L"ol", L"ul", L"li", L"dd", L"input", L"frame", L"div", NULL }; int i=0; while(stags[i]!=NULL) tags2.push_back( lem::UFString(stags[i++]) ); } for( lem::Container::size_type i=0; i<tags2.size(); ++i ) { const lem::UFString &t = tags2[i]; if( tag.eq_begi(t) && (tag.length()==t.length() || tag[ t.length() ]==L' ' ) ) return true; } return false; }
bool SG_DeclensionForm::MatchCondition( const UCString &str, const UFString &entry_flexer_flags ) const { #if !defined FAIND_NO_BOOST_REGEX if( (!valid_condition || condition.empty()) && (!valid_flexer_flags || flexer_flags.empty()) ) return true; if( valid_condition && !boost::regex_match( str.c_str(), condition ) ) return false; if( valid_flexer_flags && !boost::regex_search( entry_flexer_flags.c_str(), flexer_flags ) ) return false; return true; #else return false; #endif }
void SG_Language::LoadTxt(int Id, Macro_Parser& txt, GraphGram& gram) { // Store the beginning of language specification BSourceState beg = txt.tellp(); id = Id; name = txt.read().string(); const bool Me = gram.GetDict().GetDebugLevel_ir() >= 3; if (Me) { // Эхо-сообщение: начали трансляцию языка. gram.GetIO().mecho().printf( "%us [%vfE%us%vn]->", sol_get_token(B_LANGUAGE).c_str(), name.c_str() ); } BethToken t = txt.read(); if (t.GetToken() == B_AS) { c_name = txt.read().string(); t = txt.read(); } if (t.GetToken() != B_OFIGPAREN) { // Пустое объявление языка. txt.seekp(t.GetBegin()); } else { // Load the list of alphabets, allowed for the language. Also do load other // language parameters. while (!txt.eof()) { BethToken t = txt.read(); if (t.GetToken() == B_CFIGPAREN) break; if (t.GetToken() == B_ALPHABET) { // Add the valid alphabet name for this language BethToken abc_name = txt.read(); int id_abc = gram.Find_Alphabet(abc_name.string()); if (id_abc == UNKNOWN) { lem::Iridium::Print_Error(abc_name, txt); gram.GetIO().merr().printf("Unknown alphabet [%us] used in in language [%us] specification\n", abc_name.string().c_str(), name.c_str()); throw E_ParserError(); } alphabet.push_back(id_abc); continue; } else if (t.GetToken() == B_LINK) { Tree_Link l; l.LoadTxt(txt, gram.GetDict().GetSynGram()); txt.read_it(B_LANGUAGE); BethToken lang_name = txt.read(); int id_lang = gram.GetDict().GetSynGram().Find_Language(lang_name); if (id_lang == UNKNOWN) { lem::Iridium::Print_Error(lang_name, txt); gram.GetIO().merr().printf("Unknown language [%us] used in in language [%us] specification\n", lang_name.string().c_str(), name.c_str()); throw E_ParserError(); } lang_links.push_back(std::make_pair(l, id_lang)); continue; } else { // Синтаксис задания параметра: // 1. скалярный param_name = value // 2. векторный param_name = { value1 values2 ... } if (txt.pick().GetToken() == B_EQUAL) { txt.read_it(B_EQUAL); SG_LanguageParam *param = new SG_LanguageParam; param->name = t; if (txt.pick().GetToken() == B_OFIGPAREN) { txt.read_it(B_OFIGPAREN); while (!txt.eof()) { if (txt.pick().GetToken() == B_CFIGPAREN) { txt.read_it(B_CFIGPAREN); break; } UFString v = txt.read().GetFullStr(); v.strip(L'"'); v.trim(); param->values.push_back(v); } } else { param->values.push_back(lem::trim(lem::UFString(txt.read().GetFullStr()))); } params.push_back(param); continue; } } lem::Iridium::Print_Error(t, txt); gram.GetIO().merr().printf("Invalid token in language [%us] specification\n", name.c_str()); throw E_ParserError(); } } if (Me) { // Эхо-сообщение: закончили трансляцию. gram.GetIO().mecho().printf("%vfAOK%vn\n"); } return; }
// **************************************** // Entering the command processing loop. // **************************************** void SyntaxShell::main_loop(void) { // Если язык по умолчанию не задан, то запросим его имя с консоли. if( default_language==UNKNOWN && !guess_language ) { lem::MCollect<int> langs; default_language = sol_id->GetLanguages(langs); if( default_language==UNKNOWN || langs.size()>1 ) { while(true) { mout->printf( "Please select the language:\n" ); if( langs.empty() ) { lem::Ptr<LanguageEnumerator> lenum( sol_id->GetSynGram().languages().Enumerate() ); while( lenum->Fetch() ) langs.push_back( lenum->GetId() ); } for( lem::Container::size_type i=0; i<langs.size(); ++i ) { mout->printf( "[%vfA%d%vn] - %vfE%us%vn\n", i, sol_id->GetSynGram().languages()[langs[i]].GetName().c_str() ); } mout->printf( "%vfA-1%vn - do not set default language for syntax analysis\n\n?" ); int ilang = mkey->ask_int(); if( ilang==UNKNOWN ) { default_language = UNKNOWN; break; } if( ilang>=0 ) { default_language = langs[ilang]; break; } } } } mout->eol(); #if LEM_DEBUGGING==1 //_CrtMemState ms1,ms2,ms3; #endif int ipass=0; for(;;ipass++) { UFString str; if( !pre_entered_phrase.empty() ) { str = pre_entered_phrase; pre_entered_phrase.clear(); mout->printf( "\n> %us\n", str.c_str() ); } else { str = enter_cmd( debugger.IsNull() ? ": " : ":> " ); } if( str==L"#exit" ) break; if( TryCommand(str) ) continue; if( run_mode==TokenizerMode ) { Tokenize(str); } else if( run_mode==LemmatizerMode ) { Lemmatize(str); } else if( run_mode==SpeakerMode ) { Speak(str); } else { lem::ElapsedTime total_et; total_et.start(); PerformSyntacticAnalysis(str); total_et.stop(); const int msec_elapsed = total_et.msec(); if( traceon ) lem::mout->printf( "Elapsed time: %d millisec\n", msec_elapsed ); } } return; }
void Resource_List::LoadTxt( WideStream &txt ) { // Формат ресурсов: NNN LANG string // // Допускаются директивы: // $include filename language int last_good_id=0; const lem::UCString INCLUDE(L"$include"); const UFString cur_lang( lem::to_unicode( lem::UI::get_UI().GetCurrLang() ) ); const UFString english(L"en"); UCString nnn; std::string lang; UFString string; while( !txt.eof() ) { txt.skip_white(); nnn.clear(); lang.clear(); string.clear(); // read the number identifier (primary key) of the string record. while( !txt.eof() ) { const wchar_t u = txt.wget(); if( u==WEOF ) break; if( nnn.front()==L'#' ) { // Commentary string - read until EOL. while( !txt.eof() ) { const wchar_t u = txt.wget(); if( u == L'\n' || u==L'\r' || u==WEOF ) break; } break; } if( is_uspace(u) ) { txt.unget(u); break; } nnn += u; } if( nnn.empty() ) continue; if( nnn == INCLUDE ) { // Next fields are: 1) filename and 2) language UFString filename, language; filename.reserve(64); language.reserve(4); txt.skip_white(); while( !txt.eof() ) { const wchar_t u = txt.wget(); if( u==WEOF ) break; if( is_uspace(u) || u==L'\n' || u==L'\r' ) { txt.unget(u); break; } filename.Add_Dirty(u); } txt.skip_white(); while( !txt.eof() ) { const wchar_t u = txt.wget(); if( u==WEOF ) break; if( is_uspace(u) || u==L'\n' || u==L'\r' ) { txt.unget(u); break; } language.Add_Dirty(u); } language.calc_hash(); filename.calc_hash(); // Recursively load the file if( load_all_languages || language == cur_lang || language==english ) { // Если задан файл без указания пути, то путь берем из исходного файла lem::Path inc(filename); inc.RemoveLastLeaf(); if( inc.empty() ) { inc = txt.GetName(); inc.RemoveLastLeaf(); inc.ConcateLeaf(lem::Path(filename)); LoadTxt( inc ); } else { LoadTxt( lem::Path(filename) ); } } continue; } int iname = 0; if( lem::to_int( nnn.c_str(), &iname )==false || iname<=0 ) throw E_BaseException( lem::format_str( L"Incorrect format of string resource file: id is not a number [%ls]", nnn.c_str() ).c_str() ); last_good_id = iname; // метка языка txt.skip_white(); while( !txt.eof() ) { wchar_t u = txt.wget(); if( u==WEOF ) break; if( is_uspace(u) ) { txt.unget(u); break; } lang += static_cast<char>(u); } // Ведем список языков, для которых есть локализация ресурсов. // ищем такой язык в справочнике int ilang = FindLang(lang,NULL); int il=0; for( std::vector<std::string>::const_iterator j=langs.begin(); j!=langs.end(); j++, il++ ) if( *j == lang ) { ilang = il; break; } if( ilang==UNKNOWN && !lang.empty() ) { ilang = langs.size(); langs.push_back( lang ); } txt.skip_white(); bool apostrophed=true; // теперь сама строка ресурсов while( !txt.eof() ) { wchar_t u = txt.wget(); if( u==WEOF /*EOF fixed 17.09.2009 */ ) break; if( u==L'\r' || u=='\n' ) { break; } if( u==L'"' && string.empty() ) { // Начало строки в апострофах apostrophed = true; continue; } if( u==L'"' && !string.empty() ) { // Конец строки в апострофах // Если далее идет символ +, то будет продолжение на следующей строке. wchar_t next = txt.wget(); if( next==L'+' ) { // Это продолжение. txt.skip_white(); next = txt.wget(); if( next==WEOF || next==0 ) continue; LEM_CHECKIT_Z( next==L'"' ); continue; } break; } if( u==L'\\' ) { // спецсимволы wchar_t u2 = txt.wget(); if( u2==WEOF ) break; if( u2==L'\r' || u2=='\n' ) break; if( u2==L'r' || u2==L'n' ) u = L'\n'; else if( u2==L'"' ) u = L'"'; else u = u2; } string.Add_Dirty(u); } string.calc_hash(); if( !nnn.empty() && !string.empty() ) { // Сохраняем ресурс. // Ветка ресурса для этого nnn уже есть? string.trim(); string.strip_quotes(); Resource *r = NULL; std::map<int,Resource*>::iterator it = iname_2_res.find(iname); if( it!=iname_2_res.end() ) { r = it->second; } else { r = new Resource; r->name = iname; list.push_back(r); iname_2_res.insert( std::make_pair(iname,r) ); } r->list.push_back( make_pair( ilang, string ) ); } } return; }
void GraphGram::Save_SQL( OFormatter &out, OFormatter &alters, const SQL_Production &sql_version ) { if (sql_version.type == SQL_Production::MsSql) { out.printf("!! @echo Creating alphabets...\n"); } else if (sql_version.type == SQL_Production::Oracle) { out.printf("HOST echo Creating alphabets...\n"); } out.printf("%s\n", sql_version.BeginTx().c_str()); const wchar_t* NPrefix = sql_version.GetNPrefix(); // ПАРАМЕТРЫ -> SG_CRITERION std::unique_ptr<CriterionEnumerator> crenum(param->Enumerate()); while (crenum->Fetch()) { const int id = crenum->GetId(); const Criterion& x = crenum->GetItem(); lem::UFString name(sql_version.SqlStr(x.GetName())); lem::UFString strval(sql_version.SqlStr(x.GetString())); out.printf( "INSERT INTO sg_criterion( id, name, strval ) VALUES( %d, %us'%us', %us'%us' );\n" , id , NPrefix , name.c_str() , NPrefix , strval.c_str() ); } out.eol(); // АЛФАВИТЫ std::unique_ptr<AlphabetEnumerator> aenum(alphabets().List()); while (aenum->Fetch()) { const Alphabet &alphabet = aenum->GetItem(); const int id = aenum->GetId(); lem::UFString aname(sql_version.SqlStr(alphabet.get_Name())); out.printf( "INSERT INTO abc_alphabet( id, name ) VALUES( %d, %us'%us' );\n" , id , NPrefix , aname.c_str() ); } out.eol(); // КООРДИНАТЫ И СОСТОЯНИЯ std::unique_ptr<CoordEnumerator> cenum(coords().Enumerate()); while (cenum->Fetch()) { const int id_coord = cenum->GetId(); const GramCoord &c = cenum->GetItem(); out.printf( "INSERT INTO abc_coord( id, name, bistable ) VALUES ( %d, %us'%us', %d );\n", id_coord, NPrefix, c.GetName().front().c_str(), c.IsBistable() ? 1 : 0 ); int istate = 0; if (c.IsBistable()) { // Все-таки объявим в явном виде два состояния для бистабильных координат, чтобы // в реляционной схеме можно было создавать foreight key с таблиц SG_ENTRY_COORD и SG_FORM_COORD out.printf("INSERT INTO abc_state( id, id_coord, name ) VALUES ( 0, %d, '0' );\n", id_coord); out.printf("INSERT INTO abc_state( id, id_coord, name ) VALUES ( 1, %d, '1' );\n", id_coord); } else { for (lem::Container::size_type j = 0; j < c.states().size(); ++j) { const GramCoordState & s = c.states()[j]; const int id_parent = istate; for (lem::Container::size_type k = 0; k < s.size(); ++k, ++istate) { out.printf("INSERT INTO abc_state( id, id_coord, name ) VALUES ( %d, %d, %us'%us' );\n", istate, id_coord, NPrefix, s[k].c_str()); } } } } // КЛАССЫ -> ABC_CLASS std::unique_ptr<SymbolClassEnumerator> class_enum((SymbolClassEnumerator*)classes().Enumerate()); while (class_enum->Fetch()) { const int id = class_enum->GetId(); const GramClass & c = class_enum->GetItem(); out.printf( "INSERT INTO abc_class( id, name ) VALUES( %d, %us'%us' );\n" , id , NPrefix , sql_version.SqlStr(c.GetName()).c_str() ); // Сохраним в базе информацию о привязке координат (атрибутов, измерений, тэгов) к классам. for (lem::Container::size_type k = 0; k < c.attrs().size(); ++k) { const GramCoordAdr &atr = c.attrs()[k]; out.printf( "INSERT INTO abc_class_coord( id_class, id_coord, coord_type ) VALUES( %d, %d, 0 );\n" , id , atr.GetIndex() ); } for (lem::Container::size_type k = 0; k < c.dims().size(); ++k) { const GramCoordAdr &dim = c.dims()[k]; out.printf( "INSERT INTO abc_class_coord( id_class, id_coord, coord_type ) VALUES( %d, %d, 1 );\n" , id , dim.GetIndex() ); } } out.eol(); // ********************** // СТАТЬИ -> ABC_ENTRY // ********************** ABC_CoordPairsList coords_ref; std::unique_ptr<SymbolEnumerator> senum(entries().Enumerate()); int id_form = 0; while (senum->Fetch()) { const GG_Entry &e = senum->GetItem(); // некоторые версии MSSQL ругаются на unicode-символы с кодами более 2^16. // поэтому для этой СУБД не будем их реально загружать, но чтобы отсутствие этих // символов не вызывало удивления - впечатаем закомментированные операторы DML. bool wrap_in_comment = false; if (e.GetName() > 0x0000ffffU) { if (sql_version.type == SQL_Production::MsSql || sql_version.type == SQL_Production::Oracle || sql_version.type == SQL_Production::Postgres) { wrap_in_comment = true; } } const int id_pairs = coords_ref.Register(e.attrs()); const int id_entry = senum->GetId(); UFString s = lem::UFString(e.GetNameWide().c_str()); if (wrap_in_comment) out.printf("%s", sql_version.Get_Comment().c_str()); if (sql_version.type == SQL_Production::Oracle) { UFString s2 = SQL_Production::Oracle_UNISTR(s); out.printf( "INSERT INTO abc_entry( id, name, code, id_class, id_alphabet, id_pairs ) VALUES( %d, %us, %d, %d, %d, %d );\n" , id_entry , s2.c_str() , e.GetName() , e.GetClass() , e.GetAlphabet() , id_pairs ); } else { s = sql_version.ClearInvalidChars(s); s = sql_version.SqlStr(s); out.printf( "INSERT INTO abc_entry( id, name, code, id_class, id_alphabet, id_pairs ) VALUES( %d, %us'%us', %d, %d, %d, %d );\n" , id_entry , NPrefix , s.c_str() , e.GetName() , e.GetClass() , e.GetAlphabet() , id_pairs ); } for (Container::size_type j = 0; j < e.forms().size(); j++) { const GG_EntryForm &form = e.forms()[j]; lem::UFString fs(form.GetNameWide().c_str()); const int id_dims = coords_ref.Register(form.dims()); if (wrap_in_comment) out.printf("%s", sql_version.Get_Comment().c_str()); if (sql_version.type == SQL_Production::Oracle) { UFString s2 = SQL_Production::Oracle_UNISTR(fs); out.printf( "INSERT INTO abc_form( id, id_entry, ordnum, name, code, id_pairs )" " VALUES( %d, %d, %d, %us, %d, %d );\n" , id_form++ , id_entry , CastSizeToInt(j) , s2.c_str() , form.GetName() , id_dims ); } else { fs = sql_version.ClearInvalidChars(fs); fs = sql_version.SqlStr(fs); out.printf( "INSERT INTO abc_form( id, id_entry, ordnum, name, code, id_pairs )" " VALUES( %d, %d, %d, %us'%us', %d, %d );\n" , id_form++ , id_entry , CastSizeToInt(j) , NPrefix , fs.c_str() , form.GetName() , id_dims ); } } } if (!sql_version.norules) { // Правила слогоделителя std::unique_ptr<LS_ResultSet> rs_slb1(storage->ListSyllabRules()); while (rs_slb1->Fetch()) { const int id = rs_slb1->GetInt(0); lem::UCString name = rs_slb1->GetUCString(1); const int id_src = rs_slb1->GetInt(2); const int id_language = rs_slb1->GetInt(3); const int cursor_shift = rs_slb1->GetInt(4); out.printf("INSERT INTO slb_rule( id, name, id_src, id_language, cursor_shift ) VALUES ( %d, '%us', %d, %d, %d );\n", id, name.c_str(), id_src, id_language, cursor_shift); } rs_slb1.reset(); out.eol(); std::unique_ptr<LS_ResultSet> rs_slb2(storage->ListSyllabConditionPoints()); while (rs_slb2->Fetch()) { const int id = rs_slb2->GetInt(0); const int id_rule = rs_slb2->GetInt(1); const int point_index = rs_slb2->GetInt(2); const int n_char = rs_slb2->GetInt(3); lem::UFString char_text = rs_slb2->GetUFString(4); lem::UFString char_ucs4 = rs_slb2->GetUFString(5); const int id_class = rs_slb2->GetInt(6); const int id_entry = rs_slb2->GetInt(7); const int n_coord = rs_slb2->GetInt(8); const int id_coord0 = rs_slb2->GetInt(9); const int id_state0 = rs_slb2->GetInt(10); const int is_left_boundary = rs_slb2->GetInt(11); const int is_right_boundary = rs_slb2->GetInt(12); const int is_positive = rs_slb2->GetInt(13); out.printf("INSERT INTO slb_condition_point( id, id_rule, point_index, n_char, char_text, char_ucs4," " id_class, id_entry, id_coord0, id_state0, is_left_boundary," " is_right_boundary, n_coord, is_positive ) VALUES (" " %d, %d, %d, %d, '%us', '%us'," " %d, %d, %d, %d, %d," " %d, %d, %d );\n", id, id_rule, point_index, n_char, char_text.empty() ? L"" : char_text.c_str(), char_ucs4.empty() ? L"" : char_ucs4.c_str(), id_class, id_entry, id_coord0, id_state0, is_left_boundary, is_right_boundary, n_coord, is_positive ); } rs_slb2.reset(); out.eol(); std::unique_ptr<LS_ResultSet> rs_slb3(storage->ListSyllabResultPoints()); while (rs_slb3->Fetch()) { const int id = rs_slb3->GetInt(0); const int id_rule = rs_slb3->GetInt(1); const int point_index = rs_slb3->GetInt(2); const int copy_index = rs_slb3->GetInt(3); const int merge_index0 = rs_slb3->GetInt(4); const int merge_count = rs_slb3->GetInt(5); out.printf("INSERT INTO slb_result_point( id, id_rule, point_index, copy_index, merge_index0, merge_count )" " VALUES ( %d, %d, %d, %d, %d, %d );\n", id, id_rule, point_index, copy_index, merge_index0, merge_count); } rs_slb3.reset(); out.eol(); out.eol(); out.printf("%s\n", sql_version.CommitTx().c_str()); out.printf("%s\n", sql_version.BeginTx().c_str()); } coords_ref.SaveSQL(out, sql_version); out.eol(); out.printf("%s\n", sql_version.CommitTx().c_str()); if (sql_version.type == SQL_Production::MsSql) { out.printf("!! @echo Alphabets have been loaded.\n"); } else if (sql_version.type == SQL_Production::Oracle) { out.printf("HOST echo Alphabets have been loaded.\n"); } return; }
// ****************************************************** // Загружаем узел вместе со всеми его вложенными узлами. // ****************************************************** Node* Parser::Load_Node( WideStream *reader ) const { if( reader->eof() ) return NULL; // Пропускаем пробелы. wchar_t c=0; while( !reader->eof() ) { c = reader->wget(); if( c==WEOF ) return NULL; if( c!=L' ' && c!=L'\t' && c!=L'\r' && c!=L'\n' ) break; } // Символ должен быть '<'. if( reader->eof() ) return NULL; if( c!=L'<' ) throw Invalid_Format(); // Считываем тэг. UFString tag; Read_Tag( reader, tag ); if( tag.empty() ) throw Invalid_Format(); Node *node = new Node; Break_Tag( tag, node->name, node->attrs, node->body ); // Тэги бывают пяти видов - единичный <abc/>, открывающий <abc>, // закрывающий </abc>, комментарий <!--...-->, блок <![CDATA[ ... ]> // Для HTML требуется также специальная обработка тэгов <script>...</script> // и одиночных типа <br> if( tag.back() == L'/' ) { // Единичный тэг. node->SetClosed(true); } else if( node->name==L"![CDATA[" ) { node->node_type = Node::CDataNode; node->SetClosed(true); } // Для HTML надо проверить одиночные теги типа <br> else if( doctype==HtmlDoc && IsHtmlClosed(tag) ) { // Единичный тэг. node->SetClosed(true); } else if( tag.front()==L'/' ) { // Закрывающий тэг. // В имени убираем символ '/' node->name = remove_char( node->name, L'/' ); node->SetClosing(true); } else if( tag.front()==L'!' ) { if( tag.length()>=3 && tag.eq_beg( L"!--" ) ) { // Комментарий <!-- ... --> node->SetClosed(true); node->node_type = Node::CommentNode; } /* else if( tag.eq_beg( L"CDATA[") ) { node->SetClosed(true); node->node_type = Node::CDataNode; } */ else { if( doctype==Parser::XmlDoc ) { delete node; throw Invalid_Format(); } else { node->SetClosed(true); node->node_type = Node::InvalidNode; } } } else if( doctype==Parser::HtmlDoc && node->name.eqi(L"script") ) { // Для пары тегов <script>...</script> правила особые - тело является // произвольным набором символов, читаемых как единое целое в тело узла. node->node_type = Node::ScriptNode; node->body.reserve(256); while( !reader->eof() ) { wchar_t c = reader->wget(); if( c==WEOF || reader->eof() ) break; if( c==L'<' ) { // вдруг это начало закрывающего тэга </script> lem::UFString tbuf; tbuf.reserve(32); tbuf = c; while( !reader->eof() ) { wchar_t c2 = reader->wget(); if( c2==WEOF || reader->eof() ) break; tbuf.Add_Dirty(c2); if( c2==L'>' ) break; } if( tbuf.eqi(L"</script>") ) { node->SetClosed(true); break; } else { node->body.Add_Dirty( tbuf ); } } else { node->body.Add_Dirty(c); } } node->body.calc_hash(); } else { // Открывающий тэг. // Дальше может идти либо список вложенных тэгов, либо строка - тело. wchar_t c=0; // Пропустим пробелы. while( !reader->eof() ) { c = reader->wget(); if( c!=L' ' && c!=L'\t' && c!=L'\n' && c!=L'\r' ) // Встретили непустой символ! break; } if( c==L'<' ) { reader->unget(c); // Теперь надо загрузить все вложенные тэги и построить дерево. while( !reader->eof() ) { Node *nested = Load_Node( reader ); if( !nested ) { lem_rub_off(node); throw Invalid_Format(); } if( nested->IsComment() ) { // Комментарии удаляем. lem_rub_off(nested); } else if( nested->IsCData() ) { // Блок <[CData[ ... ]]> добавляем к телу node->body += nested->body; lem_rub_off(nested); } else if( nested->GetClosing() ) { if( nested->GetName() != node->GetName() ) { lem_rub_off(node); lem_rub_off(nested); throw Invalid_Format(); } // Список вложенных узлов закончен. node->SetClosed(true); lem_rub_off(nested); break; } else if( !nested->GetClosed() ) { lem_rub_off(node); lem_rub_off(nested); throw Invalid_Format(); } if( nested!=NULL ) { node->GetNodes().push_back( nested ); if( doctype==Parser::HtmlDoc ) { node->visible_text += nested->visible_text; } nested = NULL; } // Идем до следующего тэга. // Пропустим пробелы. while( !reader->eof() ) { c = reader->wget(); if( c!=L' ' && c!=L'\t' && c!=L'\n' && c!=L'\r' ) { // Встретили непустой символ! reader->unget(c); break; } } if( reader->eof() ) break; if( c != L'<' ) { if( doctype!=Parser::HtmlDoc ) { lem_rub_off(node); // Тело тэга может быть либо список вложенных тэгов, либо строкой. // У нас тут получается смесь. throw Invalid_Format(); } else { reader->wget(); goto load_tag_body; } } } } else { load_tag_body: // Собираем тело тэга - до закрывающего. node->body.reserve(128); bool just_started=true; while( !reader->eof() ) { lem::Stream::pos_type tpos = reader->tellp(); if( !just_started ) c = reader->wget(); else just_started = false; if( c==L'<' ) { // Начало нового тэга if( reader->wget()==L'/' ) { // это закрывающий тэг, он должен закрывать текущий тэг. reader->seekp(tpos); break; } else { // Произвольный вложенный тэг (HTML) reader->seekp(tpos); Node *nested = Load_Node(reader); if( !nested || !nested->GetClosed() ) { throw Invalid_Format(); } else if( nested->IsComment() ) { lem_rub_off(nested); } else if( nested->IsCData() ) { node->body += nested->body; lem_rub_off(nested); } if( nested!=NULL ) { node->nodes.push_back(nested); if( doctype==Parser::HtmlDoc ) { node->visible_text += nested->visible_text; } } continue; } } if( c==L'&' ) { // Далее идет либо символическое имя символа, либо его числовой код. c = reader->wget(); if( c==L'#' ) { // Считываем hex код символа до ; UFString hex; hex.reserve(6); while( !reader->eof() ) { c = reader->wget(); if( c==L';' || c==WEOF ) break; hex.Add_Dirty(c); } c = lem::to_int( hex ); } else { FString char_name; char_name.reserve(8); char_name.Add_Dirty( char(c) ); while( !reader->eof() ) { c = reader->wget(); if( c==L';' || c==WEOF ) break; char_name.Add_Dirty( char(c) ); } c = lem::CodeConverter::Sgml_2_Char(char_name); } } node->body += c; if( doctype==Parser::HtmlDoc ) { node->visible_text += c; } } if( reader->wget()!=L'<' ) { lem_rub_off(node); throw Invalid_Format(); } // Сейчас должен быть закрывающий тэг! UFString close_tag; Read_Tag( reader, close_tag ); UFString name2, body2; Collect< pair<UFString,UFString> > attrs2; Break_Tag( close_tag, name2, attrs2, body2 ); if( doctype==Parser::HtmlDoc && !remove_char( name2,L'/').eqi(node->name) ) { lem_rub_off(node); throw Invalid_Format(); } else if( remove_char(name2,L'/') != node->name ) { lem_rub_off(node); throw Invalid_Format(); } node->SetClosed(true); } } if( doctype==Parser::HtmlDoc ) { // Некоторые типы тэгов в HTML фактически вводят в текст разделитель. if( IsTextDelimiterTag( node->GetName() ) ) { node->visible_text += L' '; } } return node; }
void Parser::Break_Tag( const UFString &tag, UFString &name, Collect< pair<UFString,UFString> > &attrs, UFString &body // для ![CDATA[ ... ]] ) const { int i=0; // Пропускаем пробелы while( tag[i] ) { if( tag[i]!=L' ' && tag[i]!=L'\t' && tag[i]!=L'\r' && tag[i]!=L'\n' ) break; i++; } if( tag.eq_beg(L"![CDATA[") ) { name = L"![CDATA["; body = lem::mid( tag, 8, tag.length()-10 ); return; } // Пропускаем имя тэга while( tag[i] ) { if( tag[i]==L' ' || tag[i]==L'\t' || tag[i]==L'\r' || tag[i]==L'\n' || tag[i]==L'>' ) break; name += tag[i]; i++; } // Читаем атрибуты while( tag[i] ) { // Читаем очередную пару имя=значение // Пропускаем пробелы while( tag[i] ) { if( tag[i]!=L' ' && tag[i]!=L'\t' && tag[i]!=L'\r' && tag[i]!=L'\n' ) break; i++; } if( !tag[i] || tag[i]=='/' || tag[i]=='>' ) return; // Читаем имя атрибута = до знака '=' или пробела или конца тэга UFString var, value; if( tag[i]==L'"' ) { // В апострофах - читаем как есть до второго апострофа i++; while( tag[i] ) { if( tag[i]==L'"' ) { i++; break; } if( tag[i]==L'\n' || tag[i]=='\r' ) throw Invalid_Format(); var += tag[i]; i++; } } else { while( tag[i] ) { if( tag[i]==L'=' || tag[i]==L'/' || tag[i]==L'>' || tag[i]==L' ' || tag[i]==L'\t' || tag[i]==L'\r' || tag[i]==L'\n' ) break; var += tag[i]; i++; } } // После имени атрибута до знака '=' могут быть пробелы - пропускаем. while( tag[i] ) { if( tag[i]!=L' ' && tag[i]!=L'\t' && tag[i]!=L'\r' && tag[i]!=L'\n' ) break; i++; } if( tag[i]==L'=' ) { // Читаем значение атрибута - до пробела или конца тэга i++; // Пропускаем начальные пробелы while( tag[i] ) { if( tag[i]!=L' ' && tag[i]!=L'\t' && tag[i]!=L'\r' && tag[i]!=L'\n' ) break; i++; } if( tag[i]==L'"' ) { // Значение атрибута - в апострофах, читаем как есть i++; while( tag[i] ) { if( tag[i]==L'"' ) { i++; break; } if( tag[i]==L'\n' || tag[i]=='\r' ) throw Invalid_Format(); value += tag[i]; i++; } } else { while( tag[i] ) { if( tag[i]==L'=' || tag[i]==L'/' || tag[i]==L'>' || tag[i]==L' ' || tag[i]==L'\t' || tag[i]==L'\r' || tag[i]==L'\n' ) break; value += tag[i]; i++; } } } // Добавляем очередной атрибут attrs.push_back( make_pair( var, value ) ); } return; }
// ********************************************************** // Загружаем тэг - все символы между < >. // Открывающая угловая скобка уже считана! // ********************************************************** void Parser::Read_Tag( WideStream *reader, UFString &tag ) const { tag.clear(); int count=0; while( !reader->eof() ) { wchar_t c = reader->wget(); if( c==L'>' ) break; if( !count && c==L'!' ) { // Или комментарий <!-- ... --> // или блок кода <![CDATA[ ... ]]> // или начальный тэг <!DOCTYPE tag.Add_Dirty(c); count++; wchar_t c = reader->wget(); if( c==L'-' ) { // комментарий... tag.Add_Dirty(c); count++; while( !reader->eof() ) { wchar_t c = reader->wget(); if( c==WEOF ) break; if( count>3 && c==L'>' ) { // Комментарий заканчивается на --> if( tag.back()==L'-' && tag[tag.length()-2]==L'-' ) { goto tag_complete; } } tag.Add_Dirty(c); count++; } // Если комментарий не закончен нормально, то значит была ошибка throw Invalid_Format(); } else if( c==L'D' ) { // <!DOCTYPE ...> // загружаем как обычный тэг tag.Add_Dirty(c); count++; continue; } else if( c=='[' ) { // <![CDATA[ продолжаем загружать... tag.Add_Dirty(c); count++; continue; } else { // Неизвестный тэг, для HTML проигнорируем ошибку if( doctype==Parser::HtmlDoc ) { tag.Add_Dirty(c); count++; } else { throw Invalid_Format(); } } } else if( count==7 && c==L'[' && tag==L"![CDATA" ) { // блок кода после <![CDATA[ tag.Add_Dirty(c); count++; while( !reader->eof() ) { wchar_t c = reader->wget(); if( c==WEOF ) break; if( count>8 && c==L'>' ) { // Блок кода заканчивается на ]]> if( tag.back()==L']' && tag[tag.length()-2]==L']' ) { goto tag_complete; } } tag.Add_Dirty(c); count++; } if( doctype!=Parser::HtmlDoc ) throw Invalid_Format(); } if( c==WEOF || reader->eof() ) break; tag.Add_Dirty(c); count++; } tag_complete: tag.calc_hash(); return; }