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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: dtdparser.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:42:52  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.19
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: dtdparser.cpp,v 1000.2 2004/06/01 19:42:52 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 parser
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <serial/datatool/exceptions.hpp>
  43. #include <serial/datatool/dtdparser.hpp>
  44. #include <serial/datatool/tokens.hpp>
  45. #include <serial/datatool/module.hpp>
  46. #include <serial/datatool/moduleset.hpp>
  47. #include <serial/datatool/type.hpp>
  48. #include <serial/datatool/statictype.hpp>
  49. #include <serial/datatool/enumtype.hpp>
  50. #include <serial/datatool/reftype.hpp>
  51. #include <serial/datatool/unitype.hpp>
  52. #include <serial/datatool/blocktype.hpp>
  53. #include <serial/datatool/choicetype.hpp>
  54. #include <serial/datatool/value.hpp>
  55. #include <algorithm>
  56. #include <corelib/ncbifile.hpp>
  57. BEGIN_NCBI_SCOPE
  58. /////////////////////////////////////////////////////////////////////////////
  59. // DTDParser
  60. DTDParser::DTDParser(DTDLexer& lexer)
  61.     : AbstractParser(lexer)
  62. {
  63.     m_StackLexer.push(&lexer);
  64. }
  65. DTDParser::~DTDParser(void)
  66. {
  67. }
  68. AutoPtr<CFileModules> DTDParser::Modules(const string& fileName)
  69. {
  70.     AutoPtr<CFileModules> modules(new CFileModules(fileName));
  71.     while( Next() != T_EOF ) {
  72.         CDirEntry entry(fileName);
  73.         m_StackPath.push(entry.GetDir());
  74.         modules->AddModule(Module(entry.GetBase()));
  75.         m_StackPath.pop();
  76.     }
  77. //    CopyComments(modules->LastComments());
  78.     return modules;
  79. }
  80. AutoPtr<CDataTypeModule> DTDParser::Module(const string& name)
  81. {
  82.     AutoPtr<CDataTypeModule> module(new CDataTypeModule(name));
  83.     BuildDocumentTree();
  84. #if defined(NCBI_DTDPARSER_TRACE)
  85.     PrintDocumentTree();
  86. #endif
  87.     GenerateDataTree(*module);
  88. /*
  89.     string moduleName = ModuleReference();
  90.     AutoPtr<CDataTypeModule> module(new CDataTypeModule(moduleName));
  91.     Consume(K_DEFINITIONS, "DEFINITIONS");
  92.     Consume(T_DEFINE, "::=");
  93.     Consume(K_BEGIN, "BEGIN");
  94.     Next();
  95.     CopyComments(module->Comments());
  96.     ModuleBody(*module);
  97.     Consume(K_END, "END");
  98.     CopyComments(module->LastComments());
  99. */
  100.     return module;
  101. }
  102. void DTDParser::BuildDocumentTree(void)
  103. {
  104.     for (;;) {
  105.         try {
  106.             switch ( Next() ) {
  107.             case K_ELEMENT:
  108.                 Consume();
  109.                 BeginElementContent();
  110.                 break;
  111.             case K_ATTLIST:
  112.                 Consume();
  113.                 BeginAttributesContent();
  114.                 break;
  115.             case K_ENTITY:
  116.                 Consume();
  117.                 BeginEntityContent();
  118.                 break;
  119.             case T_ENTITY:
  120.                 // must be external entity
  121.                 PushEntityLexer(NextToken().GetText());
  122.                 break;
  123.             case T_EOF:
  124.                 if (PopEntityLexer()) {
  125.                     // was external entity
  126.                     Consume();
  127.                     break;
  128.                 } else {
  129.                     // end of doc
  130.                     return;
  131.                 }
  132.             default:
  133.                 ParseError("Invalid keyword", "keyword");
  134.                 return;
  135.             }
  136.         }
  137.         catch (CException& e) {
  138.             NCBI_RETHROW_SAME(e,"DTDParser::BuildDocumentTree: failed");
  139.         }
  140.         catch (exception& e) {
  141.             ERR_POST(e.what());
  142.             throw;
  143.         }
  144.     }
  145. }
  146. /////////////////////////////////////////////////////////////////////////////
  147. // DTDParser - elements
  148. void DTDParser::BeginElementContent(void)
  149. {
  150.     // element name
  151.     string name = NextToken().GetText();
  152.     Consume();
  153.     ParseElementContent(name, false);
  154. }
  155. void DTDParser::ParseElementContent(const string& name, bool embedded)
  156. {
  157.     DTDElement& node = m_MapElement[ name];
  158.     node.SetName(name);
  159.     switch (Next()) {
  160.     default:
  161.     case T_IDENTIFIER:
  162.         ParseError("incorrect format","element category");
  163. //        _ASSERT(0);
  164.         break;
  165.     case K_ANY:     // category
  166.         node.SetType(DTDElement::eAny);
  167.         Consume();
  168.         break;
  169.     case K_EMPTY:   // category
  170.         node.SetType(DTDElement::eEmpty);
  171.         Consume();
  172.         break;
  173.     case T_SYMBOL:     // contents. the symbol must be '('
  174.         ConsumeElementContent(node);
  175.         if (embedded) {
  176.             node.SetEmbedded();
  177.             return;
  178.         }
  179.         break;
  180.     case T_ENTITY:
  181.         PushEntityLexer(NextToken().GetText());
  182.         ConsumeElementContent(node);
  183.         PopEntityLexer();
  184.         Consume();
  185.         break;
  186.     }
  187.     // element description is ended
  188.     ConsumeSymbol('>');
  189. }
  190. void DTDParser::ConsumeElementContent(DTDElement& node)
  191. {
  192. // Element content:
  193. // http://www.w3.org/TR/2000/REC-xml-20001006#sec-element-content
  194.     string id_name;
  195.     char symbol;
  196.     int emb=0;
  197.     bool skip;
  198.     if(NextToken().GetSymbol() != '(') {
  199.         ParseError("Incorrect format","(");
  200.     }
  201. //    _ASSERT(NextToken().GetSymbol() == '(');
  202.     for (skip = false; ;) {
  203.         if (skip) {
  204.             skip=false;
  205.         } else {
  206.             Consume();
  207.         }
  208.         switch (Next()) {
  209.         default:
  210.             ParseError("Unrecognized token","token");
  211. //            _ASSERT(0);
  212.             break;
  213.         case T_IDENTIFIER:
  214.             id_name = NextToken().GetText();
  215.             if(id_name.empty()) {
  216.                 ParseError("Incorrect format","identifier");
  217.             }
  218. //            _ASSERT(!id_name.empty());
  219.             break;
  220.         case K_PCDATA:
  221.             node.SetType(DTDElement::eString);
  222.             break;
  223.         case T_SYMBOL:
  224.             switch (symbol = NextToken().GetSymbol()) {
  225.             case '(':
  226.                 // embedded content
  227.                 id_name = node.GetName();
  228.                 id_name += "__emb#__";
  229.                 id_name += NStr::IntToString(emb++);
  230.                 ParseElementContent(id_name, true);
  231.                 skip = true;
  232.                 break;
  233.             case ')':
  234.                 AddElementContent(node, id_name);
  235.                 EndElementContent( node);
  236.                 return;
  237.             case ',':
  238.             case '|':
  239.                 AddElementContent(node, id_name, symbol);
  240.                 break;
  241.             case '+':
  242.             case '*':
  243.             case '?':
  244.                 if(id_name.empty()) {
  245.                     ParseError("Incorrect format","identifier");
  246.                 }
  247. //                _ASSERT(!id_name.empty());
  248.                 node.SetOccurrence(id_name,
  249.                     symbol == '+' ? DTDElement::eOneOrMore :
  250.                         (symbol == '*' ? DTDElement::eZeroOrMore :
  251.                             DTDElement::eZeroOrOne));
  252.                 break;
  253.             default:
  254.                 ParseError("Unrecognized symbol","symbol");
  255. //                _ASSERT(0);
  256.                 break;
  257.             }
  258.             break;
  259.         case T_ENTITY:
  260.             id_name = NextToken().GetText();
  261.             PushEntityLexer(id_name);
  262.             skip = true;
  263.             break;
  264.         case T_EOF:
  265.             PopEntityLexer();
  266.             break;
  267.         }
  268.     }
  269. }
  270. void DTDParser::AddElementContent(DTDElement& node, string& id_name,
  271.     char separator)
  272. {
  273.     // id_name could be empty if the prev token was K_PCDATA
  274.     if (!id_name.empty()) {
  275.         node.AddContent(id_name);
  276.         if (separator != 0) {
  277.             node.SetType(separator == ',' ?
  278.                 DTDElement::eSequence : DTDElement::eChoice);
  279.         } else {
  280.             node.SetTypeIfUnknown(DTDElement::eSequence);
  281.         }
  282.         m_MapElement[ id_name].SetReferenced();
  283.         id_name.erase();
  284.     }
  285. }
  286. void DTDParser::EndElementContent(DTDElement& node)
  287. {
  288.     if (NextToken().GetSymbol() != ')') {
  289.         ParseError("Incorrect format", ")");
  290.     }
  291. //    _ASSERT(NextToken().GetSymbol() == ')');
  292.     Consume();
  293. // occurrence
  294.     char symbol;
  295.     switch (Next()) {
  296.     default:
  297.         break;
  298.     case T_SYMBOL:
  299.         switch (symbol = NextToken().GetSymbol()) {
  300.         default:
  301.             break;
  302.         case '+':
  303.         case '*':
  304.         case '?':
  305.             node.SetOccurrence(
  306.                 symbol == '+' ? DTDElement::eOneOrMore :
  307.                     (symbol == '*' ? DTDElement::eZeroOrMore :
  308.                         DTDElement::eZeroOrOne));
  309.             Consume();
  310.             break;
  311.         }
  312.         break;
  313.     }
  314.     FixEmbeddedNames(node);
  315. }
  316. void DTDParser::FixEmbeddedNames(DTDElement& node)
  317. {
  318.     const list<string>& refs = node.GetContent();
  319.     list<string> fixed;
  320.     for (list<string>::const_iterator i= refs.begin(); i != refs.end(); ++i) {
  321.         DTDElement& refNode = m_MapElement[*i];
  322.         if (refNode.IsEmbedded()) {
  323.             for ( int depth=1; depth<100; ++depth) {
  324.                 string testName = refNode.CreateEmbeddedName(depth);
  325.                 if (find(refs.begin(),refs.end(),testName) == refs.end()) {
  326.                     if (find(fixed.begin(),fixed.end(),testName) == fixed.end()) {
  327.                         fixed.push_back(testName);
  328.                         refNode.SetName(testName);
  329.                         break;
  330.                     }
  331.                 }
  332.             }
  333.         }
  334.     }
  335.  }
  336. /////////////////////////////////////////////////////////////////////////////
  337. // DTDParser - entities
  338. void DTDParser::BeginEntityContent(void)
  339. {
  340. // Entity:
  341. // http://www.w3.org/TR/2000/REC-xml-20001006#sec-entity-decl
  342.     TToken tok = Next();
  343.     if (tok != T_SYMBOL || NextToken().GetSymbol() != '%') {
  344.         ParseError("Incorrect format", "%");
  345.     }
  346. //    _ASSERT(tok == T_SYMBOL);
  347. //    _ASSERT(NextToken().GetSymbol() == '%');
  348.     Consume();
  349.     tok = Next();
  350.     if (tok != T_IDENTIFIER) {
  351.         ParseError("identifier");
  352.     }
  353. //    _ASSERT(tok == T_IDENTIFIER);
  354.     // entity name
  355.     string name = NextToken().GetText();
  356.     Consume();
  357.     ParseEntityContent(name);
  358. }
  359. void DTDParser::ParseEntityContent(const string& name)
  360. {
  361.     DTDEntity& node = m_MapEntity[name];
  362.     node.SetName(name);
  363.     TToken tok = Next();
  364.     if ((tok==K_SYSTEM) || (tok==K_PUBLIC)) {
  365.         node.SetExternal();
  366.         Consume();
  367.         if (tok==K_PUBLIC) {
  368.             // skip public id
  369.             tok = Next();
  370.             if (tok!=T_STRING) {
  371.                 ParseError("string");
  372.             }
  373. //            _ASSERT(tok==T_STRING);
  374.             Consume();
  375.         }
  376.         tok = Next();
  377.     }
  378.     if (tok!=T_STRING) {
  379.         ParseError("string");
  380.     }
  381. //    _ASSERT(tok==T_STRING);
  382.     node.SetData(NextToken().GetText());
  383.     Consume();
  384.     // entity description is ended
  385.     ConsumeSymbol('>');
  386. }
  387. void DTDParser::PushEntityLexer(const string& name)
  388. {
  389.     map<string,DTDEntity>::iterator i = m_MapEntity.find(name);
  390.     if (i == m_MapEntity.end()) {
  391.         ParseError("Undefined entity","entity");
  392.     }
  393. //    _ASSERT (i != m_MapEntity.end());
  394.     CNcbiIstream* in;
  395.     if (m_MapEntity[name].IsExternal()) {
  396.         string filename(m_MapEntity[name].GetData());
  397.         string fullname = CDirEntry::MakePath(m_StackPath.top(), filename);
  398.         CFile  file(fullname);
  399.         if (!file.Exists()) {
  400.             ParseError("file not found", fullname.c_str());
  401.         }
  402. //        _ASSERT(file.Exists());
  403.         in = new CNcbiIfstream(fullname.c_str());
  404.         if (!((CNcbiIfstream*)in)->is_open()) {
  405.             ParseError("cannot access file",fullname.c_str());
  406.         }
  407. //        _ASSERT(((CNcbiIfstream*)in)->is_open());
  408.         m_StackPath.push(file.GetDir());
  409.     } else {
  410.         in = new CNcbiIstrstream(m_MapEntity[name].GetData().c_str());
  411.         m_StackPath.push("");
  412.     }
  413.     DTDEntityLexer *lexer = new DTDEntityLexer(*in);
  414.     m_StackLexer.push(lexer);
  415.     SetLexer(lexer);
  416. }
  417. bool DTDParser::PopEntityLexer(void)
  418. {
  419.     if (m_StackLexer.size() > 1) {
  420.         delete m_StackLexer.top();
  421.         m_StackLexer.pop();
  422.         SetLexer(m_StackLexer.top());
  423.         m_StackPath.pop();
  424.         return true;
  425.     }
  426.     return false;
  427. }
  428. /////////////////////////////////////////////////////////////////////////////
  429. // DTDParser - attributes
  430. void DTDParser::BeginAttributesContent(void)
  431. {
  432. // Attributes
  433. // http://www.w3.org/TR/2000/REC-xml-20001006#attdecls
  434.     // element name
  435.     string name = NextToken().GetText();
  436.     Consume();
  437.     ParseAttributesContent(name);
  438. }
  439. void DTDParser::ParseAttributesContent(const string& name)
  440. {
  441.     string id_name;
  442.     DTDElement& node = m_MapElement[ name];
  443.     while (Next()==T_IDENTIFIER) {
  444.         // attribute name
  445.         id_name = NextToken().GetText();
  446.         Consume();
  447.         ConsumeAttributeContent(node, id_name);
  448.     }
  449.     // attlist description is ended
  450.     ConsumeSymbol('>');
  451. }
  452. void DTDParser::ConsumeAttributeContent(DTDElement& node,
  453.                                         const string& id_name)
  454. {
  455.     bool skip;
  456.     bool done=false;
  457.     DTDAttribute attrib;
  458.     attrib.SetName(id_name);
  459.     for (done=skip=false; !done;) {
  460.         switch(Next()) {
  461.         default:
  462.             ParseError("Unknown token", "token");
  463. //            _ASSERT(0);
  464.             break;
  465.         case T_ENTITY:
  466.             PushEntityLexer(NextToken().GetText());
  467.             skip = true;
  468.             break;
  469.         case T_EOF:
  470.             PopEntityLexer();
  471.             break;
  472.         case T_IDENTIFIER:
  473.             if (attrib.GetType() == DTDAttribute::eUnknown) {
  474.                 ParseError(attrib.GetName().c_str(), "attribute type");
  475.             }
  476.             done = true;
  477.             break;
  478.         case T_SYMBOL:
  479.             switch (NextToken().GetSymbol()) {
  480.             default:
  481.                 done = true;
  482.                 break;
  483.             case '(':
  484.                 // parse enumerated list
  485.                 attrib.SetType(DTDAttribute::eEnum);
  486.                 Consume();
  487.                 ParseEnumeratedList(attrib);
  488.                 break;
  489.             }
  490.             break;
  491.         case T_STRING:
  492.             attrib.SetValue(NextToken().GetText());
  493.             break;
  494.         case K_CDATA:
  495.             attrib.SetType(DTDAttribute::eString);
  496.             break;
  497.         case K_ID:
  498.             attrib.SetType(DTDAttribute::eId);
  499.             break;
  500.         case K_IDREF:
  501.             attrib.SetType(DTDAttribute::eIdRef);
  502.             break;
  503.         case K_IDREFS:
  504.             attrib.SetType(DTDAttribute::eIdRefs);
  505.             break;
  506.         case K_NMTOKEN:
  507.             attrib.SetType(DTDAttribute::eNmtoken);
  508.             break;
  509.         case K_NMTOKENS:
  510.             attrib.SetType(DTDAttribute::eNmtokens);
  511.             break;
  512.         case K_ENTITY:
  513.             attrib.SetType(DTDAttribute::eEntity);
  514.             break;
  515.         case K_ENTITIES:
  516.             attrib.SetType(DTDAttribute::eEntities);
  517.             break;
  518.         case K_NOTATION:
  519.             attrib.SetType(DTDAttribute::eNotation);
  520.             break;
  521.         case K_DEFAULT:
  522.             attrib.SetValueType(DTDAttribute::eDefault);
  523.             break;
  524.         case K_REQUIRED:
  525.             attrib.SetValueType(DTDAttribute::eRequired);
  526.             break;
  527.         case K_IMPLIED:
  528.             attrib.SetValueType(DTDAttribute::eImplied);
  529.             break;
  530.         case K_FIXED:
  531.             attrib.SetValueType(DTDAttribute::eFixed);
  532.             break;
  533.         }
  534.         if (skip) {
  535.             skip=false;
  536.         } else {
  537.             if (!done) {
  538.                 Consume();
  539.             }
  540.         }
  541.     }
  542.     node.AddAttribute(attrib);
  543. }
  544. void DTDParser::ParseEnumeratedList(DTDAttribute& attrib)
  545. {
  546.     for (;;) {
  547.         switch(Next()) {
  548.         default:
  549.             ParseError("Unknown token", "token");
  550. //            _ASSERT(0);
  551.             break;
  552.         case T_IDENTIFIER:
  553.             attrib.AddEnumValue(NextToken().GetText());
  554.             Consume();
  555.             break;
  556.         case T_SYMBOL:
  557.             // may be either '|' or ')'
  558.             if (NextToken().GetSymbol() == ')') {
  559.                 return;
  560.             }
  561.             Consume();
  562.             break;
  563.         case T_ENTITY:
  564.             PushEntityLexer(NextToken().GetText());
  565.             break;
  566.         case T_EOF:
  567.             PopEntityLexer();
  568.             Consume();
  569.             break;
  570.         }
  571.     }
  572. }
  573. /////////////////////////////////////////////////////////////////////////////
  574. // model generation
  575. void DTDParser::GenerateDataTree(CDataTypeModule& module)
  576. {
  577.     map<string,DTDElement>::iterator i;
  578.     for (i = m_MapElement.begin(); i != m_MapElement.end(); ++i) {
  579.         if (i->second.GetName().empty()) {
  580.             ParseError(i->first.c_str(),"definition");
  581.         }
  582.         DTDElement::EType type = i->second.GetType();
  583.         if (((type == DTDElement::eSequence) ||
  584.             (type == DTDElement::eChoice) ||
  585.             i->second.HasAttributes()) &&
  586.             !i->second.IsEmbedded())
  587.         {
  588.             ModuleType(module, i->second);
  589.         }
  590.     }
  591. }
  592. void DTDParser::ModuleType(CDataTypeModule& module, const DTDElement& node)
  593. {
  594.     AutoPtr<CDataType> type = Type(node, node.GetOccurrence(), false);
  595.     module.AddDefinition(node.GetName(), type);
  596. }
  597. AutoPtr<CDataType> DTDParser::Type(
  598.     const DTDElement& node, DTDElement::EOccurrence occ,
  599.     bool fromInside, bool ignoreAttrib)
  600. {
  601.     AutoPtr<CDataType> type(x_Type(node, occ, fromInside, ignoreAttrib));
  602.     return type;
  603. }
  604. CDataType* DTDParser::x_Type(
  605.     const DTDElement& node, DTDElement::EOccurrence occ,
  606.     bool fromInside, bool ignoreAttrib)
  607. {
  608.     CDataType* type;
  609. // if the node contains single embedded element - prune it
  610.     if ((!fromInside || node.IsEmbedded()) && !node.HasAttributes()) {
  611.         const list<string>& refs = node.GetContent();
  612.         if (refs.size() == 1) {
  613.             string refName = refs.front();
  614.             if (m_MapElement[refName].IsEmbedded() &&
  615.                 (node.GetOccurrence(refName) == DTDElement::eOne)) {
  616.                 type = x_Type(m_MapElement[refName],occ,fromInside);
  617.                 if (node.IsEmbedded()) {
  618.                     DTDElement& emb = const_cast<DTDElement&>(node);
  619.                     emb.SetName(m_MapElement[refName].GetName());
  620.                 }
  621.                 return type;
  622.             }
  623.         }
  624.     }
  625.     bool uniseq = (occ == DTDElement::eOneOrMore ||
  626.                    occ == DTDElement::eZeroOrMore);
  627.     bool cont = (node.GetType() == DTDElement::eSequence ||
  628.                  node.GetType() == DTDElement::eChoice);
  629.     bool attrib = !ignoreAttrib && node.HasAttributes();
  630.     bool ref = fromInside && !node.IsEmbedded();
  631.     if ((cont && uniseq && (attrib || node.IsEmbedded())) || (!cont && attrib)) {
  632.         if (ref) {
  633.             type = new CReferenceDataType(node.GetName());
  634.         } else {
  635.             type = CompositeNode(node, occ);
  636.             uniseq = false;
  637.         }
  638.     } else {
  639.         switch (node.GetType()) {
  640.         case DTDElement::eSequence:
  641.             if (ref) {
  642.                 type = new CReferenceDataType(node.GetName());
  643.             } else {
  644.                 type = TypesBlock(new CDataSequenceType(),node,ignoreAttrib);
  645.             }
  646.             break;
  647.         case DTDElement::eChoice:
  648.             if (ref) {
  649.                 type = new CReferenceDataType(node.GetName());
  650.             } else {
  651.                 type = TypesBlock(new CChoiceDataType(),node,ignoreAttrib);
  652.             }
  653.             break;
  654.         case DTDElement::eString:
  655.             type = new CStringDataType();
  656.             break;
  657.         case DTDElement::eAny:
  658.             type = new CAnyContentDataType();
  659.             break;
  660.         case DTDElement::eEmpty:
  661.             type = new CNullDataType();
  662.             break;
  663.         default:
  664.             ParseError("Unknown element", "element");
  665. //            _ASSERT(0);
  666.             break;
  667.         }
  668.     }
  669.     if (uniseq) {
  670.         CUniSequenceDataType* uniType = new CUniSequenceDataType(type);
  671.         uniType->SetNonEmpty( occ == DTDElement::eOneOrMore);
  672.         uniType->SetNoPrefix(true);
  673.         type = uniType;
  674.     }
  675.     return type;
  676. }
  677. CDataType* DTDParser::TypesBlock(
  678.     CDataMemberContainerType* containerType,const DTDElement& node,
  679.     bool ignoreAttrib)
  680. {
  681.     AutoPtr<CDataMemberContainerType> container(containerType);
  682.     if (!ignoreAttrib) {
  683.         AddAttributes(container, node);
  684.     }
  685.     const list<string>& refs = node.GetContent();
  686.     for (list<string>::const_iterator i= refs.begin(); i != refs.end(); ++i) {
  687.         DTDElement& refNode = m_MapElement[*i];
  688.         if (refNode.GetName().empty()) {
  689.             ParseError(i->c_str(),"definition");
  690.         }
  691.         DTDElement::EOccurrence occ = node.GetOccurrence(*i);
  692.         if (refNode.IsEmbedded()) {
  693.             occ = refNode.GetOccurrence();
  694.         }
  695.         AutoPtr<CDataType> type(Type(refNode, occ, true));
  696.         AutoPtr<CDataMember> member(new CDataMember(refNode.GetName(), type));
  697.         if ((occ == DTDElement::eZeroOrOne) ||
  698.             (occ == DTDElement::eZeroOrMore)) {
  699.             member->SetOptional();
  700.         }
  701.         if (refNode.IsEmbedded()) {
  702.             member->SetNotag();
  703.         }
  704.         member->SetNoPrefix();
  705.         container->AddMember(member);
  706.     }
  707.     return container.release();
  708. }
  709. CDataType* DTDParser::CompositeNode(
  710.     const DTDElement& node, DTDElement::EOccurrence occ)
  711. {
  712.     AutoPtr<CDataMemberContainerType> container(new CDataSequenceType());
  713.     AddAttributes(container, node);
  714.     bool uniseq =
  715.         (occ == DTDElement::eOneOrMore || occ == DTDElement::eZeroOrMore);
  716.     AutoPtr<CDataType> type(Type(node, DTDElement::eOne, false, true));
  717.     AutoPtr<CDataMember> member(new CDataMember(node.GetName(),
  718.         uniseq ? (AutoPtr<CDataType>(new CUniSequenceDataType(type))) : type));
  719.     member->SetNoPrefix();
  720.     member->SetNotag();
  721.     if (!uniseq) {
  722.         member->SetSimpleType();
  723.     }
  724.     container->AddMember(member);
  725.     return container.release();
  726. }
  727. void DTDParser::AddAttributes(
  728.     AutoPtr<CDataMemberContainerType>& container, const DTDElement& node)
  729. {
  730.     if (node.HasAttributes()) {
  731.         AutoPtr<CDataMember> member(
  732.             new CDataMember("Attlist", AttribBlock(node)));
  733.         member->SetNoPrefix();
  734.         member->SetAttlist();
  735.         container->AddMember(member);
  736.     }
  737. }
  738. CDataType* DTDParser::AttribBlock(const DTDElement& node)
  739. {
  740.     AutoPtr<CDataMemberContainerType> container(new CDataSequenceType());
  741.     const list<DTDAttribute>& att = node.GetAttributes();
  742.     for (list<DTDAttribute>::const_iterator i= att.begin();
  743.         i != att.end(); ++i) {
  744.         AutoPtr<CDataType> type(x_AttribType(*i));
  745.         AutoPtr<CDataMember> member(new CDataMember(i->GetName(), type));
  746.         string defValue( i->GetValue());
  747.         if (!defValue.empty()) {
  748.             member->SetDefault(new CIdDataValue(defValue));
  749.         }
  750.         if (i->GetValueType() == DTDAttribute::eImplied) {
  751.             member->SetOptional();
  752.         }
  753.         member->SetNoPrefix();
  754.         container->AddMember(member);
  755.     }
  756.     return container.release();
  757. }
  758. CDataType* DTDParser::x_AttribType(const DTDAttribute& att)
  759. {
  760.     CDataType* type=0;
  761.     switch (att.GetType()) {
  762.     case DTDAttribute::eUnknown:
  763.         ParseError("Unknown attribute", "attribute");
  764.         _ASSERT(0);
  765.         break;
  766.     case DTDAttribute::eId:
  767.     case DTDAttribute::eIdRef:
  768.     case DTDAttribute::eIdRefs:
  769.     case DTDAttribute::eNmtoken:
  770.     case DTDAttribute::eNmtokens:
  771.     case DTDAttribute::eEntity:
  772.     case DTDAttribute::eEntities:
  773.     case DTDAttribute::eNotation:
  774.     case DTDAttribute::eString:
  775.         type = new CStringDataType();
  776.         break;
  777.     case DTDAttribute::eEnum:
  778.         type = EnumeratedBlock(att, new CEnumDataType());
  779.         break;
  780.     }
  781.     return type;
  782. }
  783. CDataType* DTDParser::EnumeratedBlock(const DTDAttribute& att,
  784.     CEnumDataType* enumType)
  785. {
  786.     int v=1;
  787.     const list<string>& attEnums = att.GetEnumValues();
  788.     for (list<string>::const_iterator i = attEnums.begin();
  789.         i != attEnums.end(); ++i, ++v)
  790.     {
  791.         enumType->AddValue( *i, v);
  792.     }
  793.     return enumType;
  794. }
  795. /////////////////////////////////////////////////////////////////////////////
  796. // debug printing
  797. #if defined(NCBI_DTDPARSER_TRACE)
  798. void DTDParser::PrintDocumentTree(void)
  799. {
  800.     PrintEntities();
  801.     cout << " === Elements ===" << endl;
  802.     map<string,DTDElement>::iterator i;
  803.     for (i = m_MapElement.begin(); i != m_MapElement.end(); ++i) {
  804.         DTDElement& node = i->second;
  805.         DTDElement::EType type = node.GetType();
  806.         if (((type == DTDElement::eSequence) ||
  807.             (type == DTDElement::eChoice) ||
  808.             node.HasAttributes()) && !node.IsEmbedded()) {
  809.             PrintDocumentNode(i->first,i->second);
  810.         }
  811.     }
  812.     bool started = false;
  813.     for (i = m_MapElement.begin(); i != m_MapElement.end(); ++i) {
  814.         DTDElement& node = i->second;
  815.         if (node.IsEmbedded()) {
  816.             if (!started) {
  817.                 cout << " === Embedded elements ===" << endl;
  818.                 started = true;
  819.             }
  820.             PrintDocumentNode(i->first,i->second);
  821.         }
  822.     }
  823.     started = false;
  824.     for (i = m_MapElement.begin(); i != m_MapElement.end(); ++i) {
  825.         DTDElement& node = i->second;
  826.         DTDElement::EType type = node.GetType();
  827.         if (((type != DTDElement::eSequence) &&
  828.             (type != DTDElement::eChoice)) && !node.IsReferenced()) {
  829.             if (!started) {
  830.                 cout << " === UNREFERENCED elements ===" << endl;
  831.                 started = true;
  832.             }
  833.             PrintDocumentNode(i->first,i->second);
  834.         }
  835.     }
  836.     cout << endl;
  837. }
  838. void DTDParser::PrintEntities(void)
  839. {
  840.     if (!m_MapEntity.empty()) {
  841.         cout << " === Entities ===" << endl;
  842.         map<string,DTDEntity>::iterator i;
  843.         for (i = m_MapEntity.begin(); i != m_MapEntity.end(); ++i) {
  844.             cout << i->second.GetName() << " = "" << i->second.GetData() << """ << endl;
  845.         }
  846.         cout << endl;
  847.     }
  848. }
  849. void DTDParser::PrintDocumentNode(const string& name, const DTDElement& node)
  850. {
  851.     cout << name << ": ";
  852.     switch (node.GetType()) {
  853.     default:
  854.     case DTDElement::eUnknown:  cout << "unknown"; break;
  855.     case DTDElement::eString:   cout << "string";  break;
  856.     case DTDElement::eAny:      cout << "any";     break;
  857.     case DTDElement::eEmpty:    cout << "empty";   break;
  858.     case DTDElement::eSequence: cout << "sequence";break;
  859.     case DTDElement::eChoice:   cout << "choice";  break;
  860.     }
  861.     switch (node.GetOccurrence()) {
  862.     default:
  863.     case DTDElement::eOne:         cout << "(1)";    break;
  864.     case DTDElement::eOneOrMore:   cout << "(1..*)"; break;
  865.     case DTDElement::eZeroOrMore:  cout << "(0..*)"; break;
  866.     case DTDElement::eZeroOrOne:   cout << "(0..1)"; break;
  867.     }
  868.     cout << endl;
  869.     if (node.HasAttributes()) {
  870.         PrintNodeAttributes(node);
  871.     }
  872.     const list<string>& refs = node.GetContent();
  873.     if (!refs.empty()) {
  874.         cout << "        === Contents ===" << endl;
  875.         for (list<string>::const_iterator ir= refs.begin();
  876.             ir != refs.end(); ++ir) {
  877.             cout << "        " << *ir;
  878.             switch (node.GetOccurrence(*ir)) {
  879.             default:
  880.             case DTDElement::eOne:         cout << "(1)"; break;
  881.             case DTDElement::eOneOrMore:   cout << "(1..*)"; break;
  882.             case DTDElement::eZeroOrMore:  cout << "(0..*)"; break;
  883.             case DTDElement::eZeroOrOne:   cout << "(0..1)"; break;
  884.             }
  885.             cout << endl;
  886.         }
  887.     }
  888.     cout << endl;
  889. }
  890. void DTDParser::PrintNodeAttributes(const DTDElement& node)
  891. {
  892.     const list<DTDAttribute>& att = node.GetAttributes();
  893.     cout << "        === Attributes ===" << endl;
  894.     for (list<DTDAttribute>::const_iterator i= att.begin();
  895.         i != att.end(); ++i) {
  896.         cout << "        ";
  897.         cout << i->GetName();
  898.         cout << ": ";
  899.         switch (i->GetType()) {
  900.         case DTDAttribute::eUnknown:  cout << "eUnknown"; break;
  901.         case DTDAttribute::eString:   cout << "eString"; break;
  902.         case DTDAttribute::eEnum:     cout << "eEnum"; break;
  903.         case DTDAttribute::eId:       cout << "eId"; break;
  904.         case DTDAttribute::eIdRef:    cout << "eIdRef"; break;
  905.         case DTDAttribute::eIdRefs:   cout << "eIdRefs"; break;
  906.         case DTDAttribute::eNmtoken:  cout << "eNmtoken"; break;
  907.         case DTDAttribute::eNmtokens: cout << "eNmtokens"; break;
  908.         case DTDAttribute::eEntity:   cout << "eEntity"; break;
  909.         case DTDAttribute::eEntities: cout << "eEntities"; break;
  910.         case DTDAttribute::eNotation: cout << "eNotation"; break;
  911.         }
  912.         {
  913.             const list<string>& enumV = i->GetEnumValues();
  914.             if (!enumV.empty()) {
  915.                 cout << " (";
  916.                 for (list<string>::const_iterator ie= enumV.begin();
  917.                     ie != enumV.end(); ++ie) {
  918.                     if (ie != enumV.begin()) {
  919.                         cout << ",";
  920.                     }
  921.                     cout << *ie;
  922.                 }
  923.                 cout << ")";
  924.             }
  925.         }
  926.         cout << ", ";
  927.         switch (i->GetValueType()) {
  928.         case DTDAttribute::eDefault:  cout << "eDefault"; break;
  929.         case DTDAttribute::eRequired: cout << "eRequired"; break;
  930.         case DTDAttribute::eImplied:  cout << "eImplied"; break;
  931.         case DTDAttribute::eFixed:    cout << "eFixed"; break;
  932.         }
  933.         cout << ", ";
  934.         cout << """ << i->GetValue() << """;
  935.         cout << endl;
  936.     }
  937. }
  938. #endif
  939. END_NCBI_SCOPE
  940. /*
  941.  * ==========================================================================
  942.  * $Log: dtdparser.cpp,v $
  943.  * Revision 1000.2  2004/06/01 19:42:52  gouriano
  944.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.19
  945.  *
  946.  * Revision 1.19  2004/05/19 17:24:18  gouriano
  947.  * Corrected generation of C++ code by DTD for containers
  948.  *
  949.  * Revision 1.18  2004/05/17 21:03:14  gorelenk
  950.  * Added include of PCH ncbi_pch.hpp
  951.  *
  952.  * Revision 1.17  2004/04/27 18:38:53  gouriano
  953.  * In FixEmbeddedNames() not to use the same "fixed" name twice
  954.  *
  955.  * Revision 1.16  2004/04/01 14:14:02  lavr
  956.  * Spell "occurred", "occurrence", and "occurring"
  957.  *
  958.  * Revision 1.15  2004/01/12 16:51:01  gouriano
  959.  * Improved diagnostics when parsing a DTD
  960.  *
  961.  * Revision 1.14  2003/08/13 15:45:54  gouriano
  962.  * implemented generation of code, which uses AnyContent objects
  963.  *
  964.  * Revision 1.13  2003/06/24 20:55:42  gouriano
  965.  * corrected code generation and serialization of non-empty unnamed containers (XML)
  966.  *
  967.  * Revision 1.12  2003/06/16 14:41:05  gouriano
  968.  * added possibility to convert DTD to XML schema
  969.  *
  970.  * Revision 1.11  2003/03/10 18:55:18  gouriano
  971.  * use new structured exceptions (based on CException)
  972.  *
  973.  * Revision 1.10  2003/02/10 17:56:15  gouriano
  974.  * make it possible to disable scope prefixes when reading and writing objects generated from ASN specification in XML format, or when converting an ASN spec into DTD.
  975.  *
  976.  * Revision 1.9  2003/01/21 19:34:17  gouriano
  977.  * corrected parsing of entities
  978.  *
  979.  * Revision 1.8  2003/01/14 19:02:09  gouriano
  980.  * added parsing of entities as attribute contents
  981.  *
  982.  * Revision 1.7  2002/12/17 16:24:43  gouriano
  983.  * replaced _ASSERTs by throwing an exception
  984.  *
  985.  * Revision 1.6  2002/11/26 22:00:29  gouriano
  986.  * added unnamed lists of sequences (or choices) as container elements
  987.  *
  988.  * Revision 1.5  2002/11/19 19:48:28  gouriano
  989.  * added support of XML attributes of choice variants
  990.  *
  991.  * Revision 1.4  2002/11/14 21:05:27  gouriano
  992.  * added support of XML attribute lists
  993.  *
  994.  * Revision 1.3  2002/10/21 16:11:13  gouriano
  995.  * added parsing of external entities
  996.  *
  997.  * Revision 1.2  2002/10/18 14:38:56  gouriano
  998.  * added parsing of internal parsed entities
  999.  *
  1000.  * Revision 1.1  2002/10/15 13:54:01  gouriano
  1001.  * DTD lexer and parser, first version
  1002.  *
  1003.  *
  1004.  * ==========================================================================
  1005.  */