alexer.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:9k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: alexer.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:42:11  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: alexer.cpp,v 1000.1 2004/06/01 19:42:11 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author: Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Abstract lexer class
  38. *
  39. * ---------------------------------------------------------------------------
  40. * $Log: alexer.cpp,v $
  41. * Revision 1000.1  2004/06/01 19:42:11  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  43. *
  44. * Revision 1.20  2004/05/17 21:03:13  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.19  2003/03/11 20:06:47  kuznets
  48. * iterate -> ITERATE
  49. *
  50. * Revision 1.18  2003/03/10 18:55:18  gouriano
  51. * use new structured exceptions (based on CException)
  52. *
  53. * Revision 1.17  2002/05/06 19:56:12  ucko
  54. * Check for EOF at the beginning of AbstractLexer::FillChar() to handle
  55. * Compaq's iostream implementation.
  56. *
  57. * Revision 1.16  2001/06/11 14:35:02  grichenk
  58. * Added support for numeric tags in ASN.1 specifications and data streams.
  59. *
  60. * Revision 1.15  2001/05/17 15:07:11  lavr
  61. * Typos corrected
  62. *
  63. * Revision 1.14  2000/11/29 17:42:42  vasilche
  64. * Added CComment class for storing/printing ASN.1/XML module comments.
  65. * Added srcutil.hpp file to reduce file dependency.
  66. *
  67. * Revision 1.13  2000/11/20 17:26:31  vasilche
  68. * Fixed warnings on 64 bit platforms.
  69. * Updated names of config variables.
  70. *
  71. * Revision 1.12  2000/11/15 20:34:53  vasilche
  72. * Added user comments to ENUMERATED types.
  73. * Added storing of user comments to ASN.1 module definition.
  74. *
  75. * Revision 1.11  2000/11/14 21:41:23  vasilche
  76. * Added preserving of ASN.1 definition comments.
  77. *
  78. * Revision 1.10  2000/09/26 17:38:25  vasilche
  79. * Fixed incomplete choiceptr implementation.
  80. * Removed temporary comments.
  81. *
  82. * Revision 1.9  2000/08/25 15:59:19  vasilche
  83. * Renamed directory tool -> datatool.
  84. *
  85. * Revision 1.8  2000/04/07 19:26:22  vasilche
  86. * Added namespace support to datatool.
  87. * By default with argument -oR datatool will generate objects in namespace
  88. * NCBI_NS_NCBI::objects (aka ncbi::objects).
  89. * Datatool's classes also moved to NCBI namespace.
  90. *
  91. * Revision 1.7  2000/02/01 21:47:51  vasilche
  92. * Added CGeneratedChoiceTypeInfo for generated choice classes.
  93. * Removed CMemberInfo subclasses.
  94. * Added support for DEFAULT/OPTIONAL members.
  95. * Changed class generation.
  96. * Moved datatool headers to include/internal/serial/tool.
  97. *
  98. * Revision 1.6  1999/11/15 19:36:11  vasilche
  99. * Fixed warnings on GCC
  100. *
  101. * ===========================================================================
  102. */
  103. #include <ncbi_pch.hpp>
  104. #include <serial/datatool/exceptions.hpp>
  105. #include <serial/datatool/alexer.hpp>
  106. #include <serial/datatool/atoken.hpp>
  107. #include <serial/datatool/comments.hpp>
  108. BEGIN_NCBI_SCOPE
  109. #define READ_AHEAD 1024
  110. AbstractLexer::AbstractLexer(CNcbiIstream& in)
  111.     : m_Input(in), m_Line(1),
  112.       m_Buffer(new char[READ_AHEAD]), m_AllocEnd(m_Buffer + READ_AHEAD),
  113.       m_Position(m_Buffer), m_DataEnd(m_Position),
  114.       m_TokenStart(0)
  115. {
  116. }
  117. AbstractLexer::~AbstractLexer(void)
  118. {
  119.     delete []m_Buffer;
  120. }
  121. void AbstractLexer::LexerError(const char* error)
  122. {
  123.     NCBI_THROW(CDatatoolException,eWrongInput,
  124.                  "LINE " + NStr::IntToString(CurrentLine()) +
  125.                  ", TOKEN " + m_TokenText +
  126.                  " -- lexer error: " + error);
  127. }
  128. void AbstractLexer::LexerWarning(const char* error)
  129. {
  130.     ERR_POST("LINE " << CurrentLine() <<
  131.         ", TOKEN " << m_TokenText <<
  132.         " -- lexer error: " << error);
  133. }
  134. bool AbstractLexer::CheckSymbol(char symbol)
  135. {
  136.     if ( TokenStarted() ) {
  137.         return
  138.             m_NextToken.GetToken() == T_SYMBOL &&
  139.             m_NextToken.GetSymbol() == symbol;
  140.     }
  141.     LookupComments();
  142.     if ( Char() != symbol )
  143.         return false;
  144.     
  145.     FillNextToken();
  146.     _ASSERT(m_NextToken.GetToken() == T_SYMBOL &&
  147.             m_NextToken.GetSymbol() == symbol);
  148.     return true;
  149. }
  150. const string& AbstractLexer::ConsumeAndValue(void)
  151. {
  152.     if ( !TokenStarted() )
  153.         LexerError("illegal call: Consume() without NextToken()");
  154.     m_TokenText.assign(CurrentTokenStart(), CurrentTokenEnd());
  155.     m_TokenStart = 0;
  156.     return m_TokenText;
  157. }
  158. const AbstractToken& AbstractLexer::FillNextToken(void)
  159. {
  160.     _ASSERT(!TokenStarted());
  161.     FillComments();
  162.     if ( (m_NextToken.token = LookupToken()) == T_SYMBOL ) {
  163.         m_TokenStart = m_Position;
  164.         m_NextToken.line = CurrentLine();
  165.         if ( m_Position == m_DataEnd ) {
  166.             // no more data read -> EOF
  167.             m_NextToken.token = T_EOF;
  168.         }
  169.         else if ( CurrentTokenLength() == 0 ) {
  170.             AddChar();
  171.         }
  172.         else {
  173.             _ASSERT(CurrentTokenLength() == 1);
  174.         }
  175.     }
  176.     m_NextToken.start = CurrentTokenStart();
  177.     m_NextToken.length = CurrentTokenLength();
  178.     return m_NextToken;
  179. }
  180. char AbstractLexer::FillChar(size_t index)
  181. {
  182.     if (Eof()) {
  183.         return 0;
  184.     }
  185.     char* pos = m_Position + index;
  186.     if ( pos >= m_AllocEnd ) {
  187.         // char will lay outside of buffer
  188.         // first try to remove unused chars
  189.         char* used = m_Position;
  190.         if ( m_TokenStart != 0 && m_TokenStart < used )
  191.             used = m_TokenStart;
  192.         // now used if the beginning of needed data in buffer
  193.         if ( used > m_Buffer ) {
  194.             // skip nonused data at the beginning of buffer
  195.             size_t dataSize = m_DataEnd - used;
  196.             if ( dataSize > 0 ) {
  197.                 //                _TRACE("memmove(" << dataSize << ")");
  198.                 memmove(m_Buffer, used, dataSize);
  199.             }
  200.             size_t skip = used - m_Buffer;
  201.             m_Position -= skip;
  202.             m_DataEnd -= skip;
  203.             pos -= skip;
  204.             if ( m_TokenStart != 0 )
  205.                 m_TokenStart -= skip;
  206.         }
  207.         if ( pos >= m_AllocEnd ) {
  208.             // we still need longer buffer: reallocate it
  209.             // save old offsets
  210.             size_t position = m_Position - m_Buffer;
  211.             size_t dataEnd = m_DataEnd - m_Buffer;
  212.             size_t tokenStart = m_TokenStart == 0? 0: m_TokenStart - m_Buffer;
  213.             // new buffer size
  214.             size_t bufferSize = pos - m_Buffer + READ_AHEAD + 1;
  215.             // new buffer
  216.             char* buffer = new char[bufferSize];
  217.             // copy old data
  218.             //            _TRACE("memcpy(" << dataEnd << ")");
  219.             memcpy(buffer, m_Buffer, dataEnd);
  220.             // delete old buffer
  221.             delete []m_Buffer;
  222.             // restore offsets
  223.             m_Buffer = buffer;
  224.             m_AllocEnd = buffer + bufferSize;
  225.             m_Position = buffer + position;
  226.             m_DataEnd = buffer + dataEnd;
  227.             if ( m_TokenStart != 0 )
  228.                 m_TokenStart = buffer + tokenStart;
  229.             pos = m_Position + index;
  230.         }
  231.     }
  232.     while ( pos >= m_DataEnd ) {
  233.         size_t space = m_AllocEnd - m_DataEnd;
  234.         m_Input.read(m_DataEnd, space);
  235.         size_t read = m_Input.gcount();
  236.         //        _TRACE("read(" << space << ") = " << read);
  237.         if ( read == 0 )
  238.             return 0;
  239.         m_DataEnd += read;
  240.     }
  241.     return *pos;
  242. }
  243. void AbstractLexer::SkipNextComment(void)
  244. {
  245.     m_Comments.pop_front();
  246. }
  247. AbstractLexer::CComment& AbstractLexer::AddComment(void)
  248. {
  249.     m_Comments.push_back(CComment(CurrentLine()));
  250.     return m_Comments.back();
  251. }
  252. void AbstractLexer::CComment::AddChar(char c)
  253. {
  254.     m_Value += c;
  255. }
  256. void AbstractLexer::FlushComments(void)
  257. {
  258.     m_Comments.clear();
  259. }
  260. void AbstractLexer::FlushCommentsTo(CComments& comments)
  261. {
  262.     ITERATE ( list<CComment>, i, m_Comments ) {
  263.         comments.Add(i->GetValue());
  264.     }
  265.     FlushComments();
  266. }
  267. END_NCBI_SCOPE