コード例 #1
0
// *********************************************************************
// Возвращает следующий полный токен из входного потока, не перемещая
// курсор чтения.
// *********************************************************************
lem::UCString SentenceBroker::PickNextToken(void)
{
 UFString buffer;
 UCString res;

 // Сначала пропустим пробелы
 while(true)
  {
   const wchar_t c = GetChar();
   if( c==WEOF )
    break;

   buffer.Add_Dirty(c);
   if( !lem::is_uspace(c) )
    {
     res = c;
     break;  
    }
  }

 // Теперь считываем символы до любого разделителя
 while(true)
  {
   const wchar_t c = GetChar();
   if( c==WEOF )
    break;
   
   buffer.Add_Dirty(c);

   if( tokenizer->IsTokenDelimiter(c) )
    break;

   res += c;  
  }

 // Возвращаем обратно все считанные символы.
 for( int i=buffer.length()-1; i>=0; --i )
  UngetChar( buffer[i] );

 return res;
}
コード例 #2
0
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;
}
コード例 #3
0
ファイル: xp_parser.cpp プロジェクト: mcdir/GrammarEngine
// ******************************************************
// Загружаем узел вместе со всеми его вложенными узлами.
// ******************************************************
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;
}
コード例 #4
0
ファイル: xp_parser.cpp プロジェクト: mcdir/GrammarEngine
// **********************************************************
// Загружаем тэг - все символы между < >.
// Открывающая угловая скобка уже считана!
// **********************************************************
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;
}