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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: dtdlexer.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:42:49  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: dtdlexer.cpp,v 1000.2 2004/06/01 19:42:49 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: Andrei Gourianov
  35. *
  36. * File Description:
  37. *   DTD lexer
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <serial/datatool/dtdlexer.hpp>
  43. #include <serial/datatool/tokens.hpp>
  44. BEGIN_NCBI_SCOPE
  45. DTDLexer::DTDLexer(CNcbiIstream& in)
  46.     : AbstractLexer(in)
  47. {
  48.     m_CharsToSkip = 0;
  49. }
  50. DTDLexer::~DTDLexer(void)
  51. {
  52. }
  53. TToken DTDLexer::LookupToken(void)
  54. {
  55.     TToken tok;
  56.     char c = Char();
  57.     switch (c) {
  58.     case '<':
  59.         if (Char(1)=='!') {
  60.             SkipChars(2);
  61.             if (isalpha(Char())) {
  62.                 return LookupIdentifier();
  63.             } else {
  64.                 LexerError("name must start with a letter (alpha)");
  65. //                _ASSERT(0);
  66.             }
  67.         } else {
  68.              // not allowed in DTD
  69.              LexerError("Incorrect format");
  70. //             _ASSERT(0);
  71.         }
  72.         break;
  73.     case '#':
  74.         tok = LookupIdentifier();
  75.         if (tok == T_IDENTIFIER) {
  76.             LexerError("Unknown keyword");
  77.         }
  78. //        _ASSERT(tok != T_IDENTIFIER);
  79.         return tok;
  80.     case '%':
  81.         tok = LookupEntity();
  82.         return tok;
  83.     case '"':
  84.     case ''':
  85.         if (!EndPrevToken()) {
  86.             tok = LookupString();
  87.             return tok;
  88.         }
  89.         break;
  90.     default:
  91.         if (isalpha(c)) {
  92.             tok = LookupIdentifier();
  93.             return tok;
  94.         }
  95.         break;
  96.     }
  97.     return T_SYMBOL;
  98. }
  99. //  find all comments and insert them into Lexer
  100. void DTDLexer::LookupComments(void)
  101. {
  102.     EndPrevToken();
  103.     char c;
  104.     for (;;) {
  105.         c = Char();
  106.         switch (c) {
  107.         case ' ':
  108.         case 't':
  109.         case 'r':
  110.             SkipChar();
  111.             break;
  112.         case 'n':
  113.             SkipChar();
  114.             NextLine();
  115.             break;
  116.         case '<':
  117.             if ((Char(1) == '!') && (Char(2) == '-') && (Char(3) == '-')) {
  118.                 // comment started
  119.                 SkipChars(4);
  120.                 while (ProcessComment())
  121.                     ;
  122.                 break;
  123.             }
  124.             return; // if it is not comment, it is token
  125.         default:
  126.             return;
  127.         }
  128.     }
  129. }
  130. bool DTDLexer::ProcessComment(void)
  131. {
  132.     CComment& comment = AddComment();
  133.     for (;;) {
  134.         char c = Char();
  135.         switch ( c ) {
  136.         case 'r':
  137.             SkipChar();
  138.             break;
  139.         case 'n':
  140.             SkipChar();
  141.             NextLine();
  142.             return true; // comment not ended - there is more
  143.         case 0:
  144.             if ( Eof() )
  145.                 return false;
  146.             break;
  147.         case '-':
  148.             if ((Char(1) == '-') && (Char(2) == '>')) {
  149.                 // end of the comment
  150.                 SkipChars(3);
  151.                 return false;
  152.             }
  153.             // no break here
  154.         default:
  155.             comment.AddChar(c);
  156.             SkipChar();
  157.             break;
  158.         }
  159.     }
  160.     return false;
  161. }
  162. TToken DTDLexer::LookupIdentifier(void)
  163. {
  164.     StartToken();
  165. // something (not comment) started
  166. // find where it ends
  167.     for (char c = Char(); c != 0; c = Char()) {
  168. // complete specification is here:
  169. // http://www.w3.org/TR/2000/REC-xml-20001006#sec-common-syn
  170.         if (isalnum(c) || strchr("#._-:", c)) {
  171.             AddChar();
  172.         } else {
  173.             break;
  174.         }
  175.     }
  176.     return LookupKeyword();
  177. }
  178. #define CHECK(keyword, t, length) 
  179.     if ( memcmp(token, keyword, length) == 0 ) return t
  180. TToken DTDLexer::LookupKeyword(void)
  181. {
  182.     const char* token = CurrentTokenStart();
  183. // check identifier against known keywords
  184.     switch ( CurrentTokenLength() ) {
  185.     default:
  186.         break;
  187.     case 2:
  188.         CHECK("ID",K_ID,2);
  189.         break;
  190.     case 3:
  191.         CHECK("ANY", K_ANY,  3);
  192.         break;
  193.     case 5:
  194.         CHECK("EMPTY", K_EMPTY,  5);
  195.         CHECK("CDATA", K_CDATA,  5);
  196.         CHECK("IDREF", K_IDREF,  5);
  197.         break;
  198.     case 6:
  199.         CHECK("ENTITY", K_ENTITY, 6);
  200.         CHECK("SYSTEM", K_SYSTEM, 6);
  201.         CHECK("PUBLIC", K_PUBLIC, 6);
  202.         CHECK("IDREFS", K_IDREFS, 6);
  203.         CHECK("#FIXED", K_FIXED,  6);
  204.         break;
  205.     case 7:
  206.         CHECK("ELEMENT", K_ELEMENT, 7);
  207.         CHECK("ATTLIST", K_ATTLIST, 7);
  208.         CHECK("#PCDATA", K_PCDATA,  7);
  209.         CHECK("NMTOKEN", K_NMTOKEN, 7);
  210.         break;
  211.     case 8:
  212.         CHECK("NMTOKENS", K_NMTOKENS, 8);
  213.         CHECK("ENTITIES", K_ENTITIES, 8);
  214.         CHECK("NOTATION", K_NOTATION, 8);
  215.         CHECK("#DEFAULT", K_DEFAULT,  8);
  216.         CHECK("#IMPLIED", K_IMPLIED,  8);
  217.         break;
  218.     case 9:
  219.         CHECK("#REQUIRED", K_REQUIRED, 9);
  220.         break;
  221.     }
  222.     return T_IDENTIFIER;
  223. }
  224. TToken DTDLexer::LookupEntity(void)
  225. {
  226. // Entity declaration:
  227. // http://www.w3.org/TR/2000/REC-xml-20001006#sec-entity-decl
  228.     char c = Char();
  229.     if (c != '%') {
  230.         LexerError("Unexpected symbol: %");
  231.     }
  232. //    _ASSERT(c == '%');
  233.     if (isspace(Char(1))) {
  234.         return T_SYMBOL;
  235.     } else if (isalpha(Char(1))) {
  236.         SkipChar();
  237.         StartToken();
  238.         for (c = Char(); c != ';'; c = Char()) {
  239.             AddChar();
  240.         }
  241.         m_CharsToSkip = 1;
  242.     } else {
  243.         LexerError("Unexpected symbol");
  244.     }
  245.     return T_ENTITY;
  246. }
  247. TToken DTDLexer::LookupString(void)
  248. {
  249. // Entity value:
  250. // http://www.w3.org/TR/2000/REC-xml-20001006#NT-EntityValue
  251.     _ASSERT(m_CharsToSkip==0);
  252.     char c0 = Char();
  253.     if(c0 != '"' && c0 != ''') {
  254.         LexerError("Unexpected symbol");
  255.     }
  256. //    _ASSERT(c0 == '"' || c0 == ''');
  257.     SkipChar();
  258.     StartToken();
  259.     m_CharsToSkip = 1;
  260.     for (char c = Char(); c != c0; c = Char()) {
  261.         AddChar();
  262.     }
  263.     return T_STRING;
  264. }
  265. bool  DTDLexer::EndPrevToken(void)
  266. {
  267.     if (m_CharsToSkip != 0) {
  268.         SkipChars(m_CharsToSkip);
  269.         m_CharsToSkip = 0;
  270.         return true;
  271.     }
  272.     return false;
  273. }
  274. END_NCBI_SCOPE
  275. /*
  276.  * ==========================================================================
  277.  * $Log: dtdlexer.cpp,v $
  278.  * Revision 1000.2  2004/06/01 19:42:49  gouriano
  279.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  280.  *
  281.  * Revision 1.7  2004/05/17 21:03:14  gorelenk
  282.  * Added include of PCH ncbi_pch.hpp
  283.  *
  284.  * Revision 1.6  2004/01/16 19:56:52  gouriano
  285.  * Minor correction when parsing end-of-line
  286.  *
  287.  * Revision 1.5  2002/12/17 16:24:43  gouriano
  288.  * replaced _ASSERTs by throwing an exception
  289.  *
  290.  * Revision 1.4  2002/11/14 21:05:27  gouriano
  291.  * added support of XML attribute lists
  292.  *
  293.  * Revision 1.3  2002/10/21 16:09:46  gouriano
  294.  * added more DTD tokens
  295.  *
  296.  * Revision 1.2  2002/10/18 14:38:56  gouriano
  297.  * added parsing of internal parsed entities
  298.  *
  299.  * Revision 1.1  2002/10/15 13:54:01  gouriano
  300.  * DTD lexer and parser, first version
  301.  *
  302.  *
  303.  * ==========================================================================
  304.  */