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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: parser.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:43:29  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.35
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: parser.cpp,v 1000.2 2004/06/01 19:43:29 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. *   ASN.1 parser
  38. *
  39. * ---------------------------------------------------------------------------
  40. * $Log: parser.cpp,v $
  41. * Revision 1000.2  2004/06/01 19:43:29  gouriano
  42. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.35
  43. *
  44. * Revision 1.35  2004/05/17 21:03:14  gorelenk
  45. * Added include of PCH ncbi_pch.hpp
  46. *
  47. * Revision 1.34  2004/02/26 16:24:59  gouriano
  48. * Skip datatype constraints when parsing ASN.1 spec
  49. *
  50. * Revision 1.33  2004/02/25 19:45:19  gouriano
  51. * Made it possible to define DEFAULT for data members of type REAL
  52. *
  53. * Revision 1.32  2003/10/21 13:48:51  grichenk
  54. * Redesigned type aliases in serialization library.
  55. * Fixed the code (removed CRef-s, added explicit
  56. * initializers etc.)
  57. *
  58. * Revision 1.31  2003/05/22 20:10:25  gouriano
  59. * added UTF8 strings
  60. *
  61. * Revision 1.30  2003/05/14 14:41:36  gouriano
  62. * corrected writing comments
  63. *
  64. * Revision 1.29  2003/03/10 18:55:18  gouriano
  65. * use new structured exceptions (based on CException)
  66. *
  67. * Revision 1.28  2002/01/28 17:00:15  coremake
  68. * Fixed MIPSpro 7.3.1.2m SEGVs on throw/catch
  69. *
  70. * Revision 1.27  2001/06/11 14:35:02  grichenk
  71. * Added support for numeric tags in ASN.1 specifications and data streams.
  72. *
  73. * Revision 1.26  2000/12/15 15:38:51  vasilche
  74. * Added support of Int8 and long double.
  75. * Added support of BigInt ASN.1 extension - mapped to Int8.
  76. * Enum values now have type Int4 instead of long.
  77. *
  78. * Revision 1.25  2000/11/15 20:34:55  vasilche
  79. * Added user comments to ENUMERATED types.
  80. * Added storing of user comments to ASN.1 module definition.
  81. *
  82. * Revision 1.24  2000/11/14 21:41:25  vasilche
  83. * Added preserving of ASN.1 definition comments.
  84. *
  85. * Revision 1.23  2000/11/01 20:38:59  vasilche
  86. * OPTIONAL and DEFAULT are not permitted in CHOICE.
  87. * Fixed code generation for DEFAULT.
  88. *
  89. * Revision 1.22  2000/09/26 17:38:26  vasilche
  90. * Fixed incomplete choiceptr implementation.
  91. * Removed temporary comments.
  92. *
  93. * Revision 1.21  2000/08/25 15:59:23  vasilche
  94. * Renamed directory tool -> datatool.
  95. *
  96. * Revision 1.20  2000/04/07 19:26:32  vasilche
  97. * Added namespace support to datatool.
  98. * By default with argument -oR datatool will generate objects in namespace
  99. * NCBI_NS_NCBI::objects (aka ncbi::objects).
  100. * Datatool's classes also moved to NCBI namespace.
  101. *
  102. * Revision 1.19  2000/02/01 21:48:04  vasilche
  103. * Added CGeneratedChoiceTypeInfo for generated choice classes.
  104. * Removed CMemberInfo subclasses.
  105. * Added support for DEFAULT/OPTIONAL members.
  106. * Changed class generation.
  107. * Moved datatool headers to include/internal/serial/tool.
  108. *
  109. * Revision 1.18  2000/01/10 19:46:45  vasilche
  110. * Fixed encoding/decoding of REAL type.
  111. * Fixed encoding/decoding of StringStore.
  112. * Fixed encoding/decoding of NULL type.
  113. * Fixed error reporting.
  114. * Reduced object map (only classes).
  115. *
  116. * Revision 1.17  1999/12/28 18:55:59  vasilche
  117. * Reduced size of compiled object files:
  118. * 1. avoid inline or implicit virtual methods (especially destructors).
  119. * 2. avoid std::string's methods usage in inline methods.
  120. * 3. avoid string literals ("xxx") in inline methods.
  121. *
  122. * Revision 1.16  1999/12/03 21:42:12  vasilche
  123. * Fixed conflict of enums in choices.
  124. *
  125. * Revision 1.15  1999/11/19 15:48:10  vasilche
  126. * Modified AutoPtr template to allow its use in STL containers (map, vector etc.)
  127. *
  128. * Revision 1.14  1999/11/15 19:36:18  vasilche
  129. * Fixed warnings on GCC
  130. *
  131. * ===========================================================================
  132. */
  133. #include <ncbi_pch.hpp>
  134. #include <serial/datatool/parser.hpp>
  135. #include <serial/datatool/tokens.hpp>
  136. #include <serial/datatool/module.hpp>
  137. #include <serial/datatool/moduleset.hpp>
  138. #include <serial/datatool/type.hpp>
  139. #include <serial/datatool/statictype.hpp>
  140. #include <serial/datatool/enumtype.hpp>
  141. #include <serial/datatool/reftype.hpp>
  142. #include <serial/datatool/unitype.hpp>
  143. #include <serial/datatool/blocktype.hpp>
  144. #include <serial/datatool/choicetype.hpp>
  145. #include <serial/datatool/value.hpp>
  146. BEGIN_NCBI_SCOPE
  147. AutoPtr<CFileModules> ASNParser::Modules(const string& fileName)
  148. {
  149. // BUG:  MIPSpro 7.3.1.2m SEGVs on throw/catch from function:
  150. //   CDataTypeModule::Resolve(const string& typeName)
  151. // This is apparently not needed for MIPSpro 7.3.1.1m. -- First
  152. // problems appeared with MIPSpro 7.3.1.2m.
  153. // This also helps if this artificial catch is put to function:
  154. //   CDataTool::LoadDefinitions()
  155. #if defined(NCBI_COMPILER_MIPSPRO)
  156. #  if NCBI_COMPILER_VERSION == 730
  157.     try {
  158.         throw runtime_error("MIPS_EXC_BUG");
  159.     }
  160.     catch (...) {
  161.     }
  162. #  endif
  163. #endif
  164.     AutoPtr<CFileModules> modules(new CFileModules(fileName));
  165.     while ( Next() != T_EOF ) {
  166.         modules->AddModule(Module());
  167.     }
  168.     CopyComments(modules->LastComments());
  169.     return modules;
  170. }
  171. AutoPtr<CDataTypeModule> ASNParser::Module(void)
  172. {
  173.     string moduleName = ModuleReference();
  174.     AutoPtr<CDataTypeModule> module(new CDataTypeModule(moduleName));
  175.     Consume(K_DEFINITIONS, "DEFINITIONS");
  176.     Consume(T_DEFINE, "::=");
  177.     Consume(K_BEGIN, "BEGIN");
  178.     Next();
  179.     CopyComments(module->Comments());
  180.     ModuleBody(*module);
  181.     Consume(K_END, "END");
  182.     CopyComments(module->LastComments());
  183.     return module;
  184. }
  185. void ASNParser::Imports(CDataTypeModule& module)
  186. {
  187.     do {
  188.         list<string> types;
  189.         TypeList(types);
  190.         Consume(K_FROM, "FROM");
  191.         module.AddImports(ModuleReference(), types);
  192.     } while ( !ConsumeIfSymbol(';') );
  193. }
  194. void ASNParser::Exports(CDataTypeModule& module)
  195. {
  196.     list<string> types;
  197.     TypeList(types);
  198.     module.AddExports(types);
  199.     ConsumeSymbol(';');
  200. }
  201. void ASNParser::ModuleBody(CDataTypeModule& module)
  202. {
  203.     string name;
  204.     while ( true ) {
  205.         try {
  206.             switch ( Next() ) {
  207.             case K_EXPORTS:
  208.                 Consume();
  209.                 Exports(module);
  210.                 CopyComments(module.Comments());
  211.                 break;
  212.             case K_IMPORTS:
  213.                 Consume();
  214.                 Imports(module);
  215.                 CopyComments(module.Comments());
  216.                 break;
  217.             case T_TYPE_REFERENCE:
  218.             case T_IDENTIFIER:
  219.                 name = TypeReference();
  220.                 Consume(T_DEFINE, "::=");
  221.                 ModuleType(module, name);
  222.                 break;
  223.             case T_DEFINE:
  224.                 ERR_POST("LINE " << Location() <<
  225.                     " type name omitted");
  226.                 Consume();
  227.                 ModuleType(module, "unnamed type");
  228.                 break;
  229.             case K_END:
  230.                 return;
  231.             default:
  232.                 ERR_POST("LINE " << Location() <<
  233.                     " type definition expected");
  234.                 return;
  235.             }
  236.         }
  237.         catch (CException& e) {
  238.             NCBI_RETHROW_SAME(e,"ASNParser::ModuleBody: failed");
  239.         }
  240.         catch (exception& e) {
  241.             ERR_POST(e.what());
  242.         }
  243.     }
  244. }
  245. void ASNParser::ModuleType(CDataTypeModule& module, const string& name)
  246. {
  247.     AutoPtr<CDataType> type = Type();
  248.     CopyLineComment(LastTokenLine(), type->Comments(),
  249.                     eCombineNext);
  250.     if (type->IsStdType()  ||  type->IsReference()) {
  251.         type->SetIsAlias(true);
  252.     }
  253.     module.AddDefinition(name, type);
  254. }
  255. AutoPtr<CDataType> ASNParser::Type(void)
  256. {
  257.     int line = NextTokenLine();
  258.     AutoPtr<CDataType> type(x_Type());
  259.     type->SetSourceLine(line);
  260.     return type;
  261. }
  262. CDataType* ASNParser::x_Type(void)
  263. {
  264.     TToken tok = Next();
  265.     switch ( tok ) {
  266.     case K_BOOLEAN:
  267.         Consume();
  268.         return new CBoolDataType();
  269.     case K_INTEGER:
  270.         Consume();
  271.         if ( CheckSymbol('{') )
  272.             return EnumeratedBlock(new CIntEnumDataType());
  273.         else
  274.             return new CIntDataType();
  275.     case K_BIGINT:
  276.         Consume();
  277.         if ( CheckSymbol('{') )
  278.             return EnumeratedBlock(new CBigIntEnumDataType());
  279.         else
  280.             return new CBigIntDataType();
  281.     case K_ENUMERATED:
  282.         Consume();
  283.         return EnumeratedBlock(new CEnumDataType());
  284.     case K_REAL:
  285.         Consume();
  286.         return new CRealDataType();
  287.     case K_BIT:
  288.         Consume();
  289.         Consume(K_STRING, "STRING");
  290.         return new CBitStringDataType();
  291.     case K_OCTET:
  292.         Consume();
  293.         Consume(K_STRING, "STRING");
  294.         return new COctetStringDataType();
  295.     case K_NULL:
  296.         Consume();
  297.         return new CNullDataType();
  298.     case K_SEQUENCE:
  299.         Consume();
  300.         if ( ConsumeIf(K_OF) )
  301.             return new CUniSequenceDataType(Type());
  302.         else
  303.             return TypesBlock(new CDataSequenceType(), true);
  304.     case K_SET:
  305.         Consume();
  306.         if ( ConsumeIf(K_OF) )
  307.             return new CUniSetDataType(Type());
  308.         else
  309.             return TypesBlock(new CDataSetType(), true);
  310.     case K_CHOICE:
  311.         Consume();
  312.         return TypesBlock(new CChoiceDataType(), false);
  313.     case K_VisibleString:
  314.     case K_UTF8String:
  315.         Consume();
  316.         return new CStringDataType(
  317.             tok == K_UTF8String ?
  318.                 CStringDataType::eStringTypeUTF8 :
  319.                 CStringDataType::eStringTypeVisible);
  320.     case K_StringStore:
  321.         Consume();
  322.         return new CStringStoreDataType();
  323.     case T_IDENTIFIER:
  324.     case T_TYPE_REFERENCE:
  325.         return new CReferenceDataType(TypeReference());
  326.     case T_TAG:
  327.         string val = ConsumeAndValue();
  328.         CDataType* tagged = x_Type();
  329.         tagged->SetTag(NStr::StringToInt(val.substr(1, val.length()-2)));
  330.         return tagged;
  331.     }
  332.     ParseError("type");
  333. return 0;
  334. }
  335. bool ASNParser::HaveMoreElements(void)
  336. {
  337.     const AbstractToken& token = NextToken();
  338.     if ( token.GetToken() == T_SYMBOL ) {
  339.         switch ( token.GetSymbol() ) {
  340.         case ',':
  341.             Consume();
  342.             return true;
  343.         case '}':
  344.             Consume();
  345.             return false;
  346.         case '(':
  347.             Consume();
  348.     // skip constraints definition
  349.             SkipTo(')');
  350.             return HaveMoreElements();
  351.         }
  352.     }
  353.     ParseError("',' or '}'");
  354.     return false;
  355. }
  356. void ASNParser::SkipTo(char ch)
  357. {
  358.     for ( TToken tok = Next(); tok != T_EOF; tok = Next() ) {
  359.         if (tok == T_SYMBOL && NextToken().GetSymbol() == ch) {
  360.             Consume();
  361.             return;
  362.         }
  363.         Consume();
  364.     }
  365. }
  366. CDataType* ASNParser::TypesBlock(CDataMemberContainerType* containerType,
  367.                                  bool allowDefaults)
  368. {
  369.     AutoPtr<CDataMemberContainerType> container(containerType);
  370.     int line = NextTokenLine();
  371.     ConsumeSymbol('{');
  372.     CopyLineComment(line, container->Comments(), eCombineNext);
  373.     for ( bool more = true; more; ) {
  374.         line = NextTokenLine();
  375.         AutoPtr<CDataMember> member = NamedDataType(allowDefaults);
  376.         more = HaveMoreElements();
  377.         if ( more )
  378.             CopyLineComment(line, member->Comments(), eCombineNext);
  379.         else
  380.             CopyLineComment(line, member->Comments());
  381.         container->AddMember(member);
  382.     }
  383.     return container.release();
  384. }
  385. AutoPtr<CDataMember> ASNParser::NamedDataType(bool allowDefaults)
  386. {
  387.     string name;
  388.     if ( Next() == T_IDENTIFIER )
  389.         name = Identifier();
  390.     AutoPtr<CDataType> type(Type());
  391.     AutoPtr<CDataMember> member(new CDataMember(name, type));
  392.     if ( allowDefaults ) {
  393.         switch ( Next() ) {
  394.         case K_OPTIONAL:
  395.             Consume();
  396.             member->SetOptional();
  397.             break;
  398.         case K_DEFAULT:
  399.             Consume();
  400.             member->SetDefault(Value());
  401.             break;
  402.         }
  403.     }
  404.     CopyComments(member->Comments());
  405.     return member;
  406. }
  407. CEnumDataType* ASNParser::EnumeratedBlock(CEnumDataType* enumType)
  408. {
  409.     AutoPtr<CEnumDataType> e(enumType);
  410.     int line = NextTokenLine();
  411.     ConsumeSymbol('{');
  412.     CopyLineComment(line, e->Comments(), eCombineNext);
  413.     for ( bool more = true; more; ) {
  414.         line = NextTokenLine();
  415.         CEnumDataTypeValue& value = EnumeratedValue(*e);
  416.         more = HaveMoreElements();
  417.         CopyLineComment(line, value.GetComments(), eCombineNext);
  418.     }
  419.     return e.release();
  420. }
  421. CEnumDataTypeValue& ASNParser::EnumeratedValue(CEnumDataType& t)
  422. {
  423.     string id = Identifier();
  424.     ConsumeSymbol('(');
  425.     Int4 value = Number();
  426.     ConsumeSymbol(')');
  427.     CEnumDataTypeValue& ret = t.AddValue(id, value);
  428.     CopyComments(ret.GetComments());
  429.     return ret;
  430. }
  431. void ASNParser::TypeList(list<string>& ids)
  432. {
  433.     do {
  434.         ids.push_back(TypeReference());
  435.     } while ( ConsumeIfSymbol(',') );
  436. }
  437. AutoPtr<CDataValue> ASNParser::Value(void)
  438. {
  439.     int line = NextTokenLine();
  440.     AutoPtr<CDataValue> value(x_Value());
  441.     value->SetSourceLine(line);
  442.     return value;
  443. }
  444. AutoPtr<CDataValue> ASNParser::x_Value(void)
  445. {
  446.     switch ( Next() ) {
  447.     case T_NUMBER:
  448.         return AutoPtr<CDataValue>(new CIntDataValue(Number()));
  449.     case T_DOUBLE:
  450.         return AutoPtr<CDataValue>(new CDoubleDataValue(Double()));
  451.     case T_STRING:
  452.         return AutoPtr<CDataValue>(new CStringDataValue(String()));
  453.     case K_NULL:
  454.         Consume();
  455.         return AutoPtr<CDataValue>(new CNullDataValue());
  456.     case K_FALSE:
  457.         Consume();
  458.         return AutoPtr<CDataValue>(new CBoolDataValue(false));
  459.     case K_TRUE:
  460.         Consume();
  461.         return AutoPtr<CDataValue>(new CBoolDataValue(true));
  462.     case T_IDENTIFIER:
  463.         {
  464.             string id = Identifier();
  465.             if ( CheckSymbols(',', '}') )
  466.                 return AutoPtr<CDataValue>(new CIdDataValue(id));
  467.             else
  468.                 return AutoPtr<CDataValue>(new CNamedDataValue(id, Value()));
  469.         }
  470.     case T_BINARY_STRING:
  471.     case T_HEXADECIMAL_STRING:
  472.         return AutoPtr<CDataValue>(new CBitStringDataValue(ConsumeAndValue()));
  473.     case T_SYMBOL:
  474.         switch ( NextToken().GetSymbol() ) {
  475.         case '-':
  476.             return AutoPtr<CDataValue>(new CIntDataValue(Number()));
  477.         case '{':
  478.             {
  479.                 Consume();
  480.                 AutoPtr<CBlockDataValue> b(new CBlockDataValue());
  481.                 if ( !CheckSymbol('}') ) {
  482.                     do {
  483.                         b->GetValues().push_back(Value());
  484.                     } while ( ConsumeIfSymbol(',') );
  485.                 }
  486.                 ConsumeSymbol('}');
  487.                 return AutoPtr<CDataValue>(b.release());
  488.             }
  489.         }
  490. break;
  491.     }
  492.     ParseError("value");
  493. return AutoPtr<CDataValue>(0);
  494. }
  495. Int4 ASNParser::Number(void)
  496. {
  497.     return NStr::StringToInt(ValueOf(T_NUMBER, "number"));
  498. }
  499. double ASNParser::Double(void)
  500. {
  501.     return NStr::StringToDouble(ValueOf(T_DOUBLE, "double"));
  502. }
  503. const string& ASNParser::String(void)
  504. {
  505.     Expect(T_STRING, "string");
  506.     Consume();
  507.     return L().StringValue();
  508. }
  509. const string& ASNParser::Identifier(void)
  510. {
  511.     switch ( Next() ) {
  512.     case T_TYPE_REFERENCE:
  513.         ERR_POST("LINE " << Location() <<
  514.             " identifier must begin with lowercase letter");
  515.         return ConsumeAndValue();
  516.     case T_IDENTIFIER:
  517.         return ConsumeAndValue();
  518.     }
  519.     ParseError("identifier");
  520. return NcbiEmptyString;
  521. }
  522. const string& ASNParser::TypeReference(void)
  523. {
  524.     switch ( Next() ) {
  525.     case T_TYPE_REFERENCE:
  526.         return ConsumeAndValue();
  527.     case T_IDENTIFIER:
  528.         ERR_POST("LINE " << Location() <<
  529.             " type name must begin with uppercase letter");
  530.         return ConsumeAndValue();
  531.     }
  532.     ParseError("type name");
  533. return NcbiEmptyString;
  534. }
  535. const string& ASNParser::ModuleReference(void)
  536. {
  537.     switch ( Next() ) {
  538.     case T_TYPE_REFERENCE:
  539.         return ConsumeAndValue();
  540.     case T_IDENTIFIER:
  541.         ERR_POST("LINE " << Location() <<
  542.             " module name must begin with uppercase letter");
  543.         return ConsumeAndValue();
  544.     }
  545.     ParseError("module name");
  546. return NcbiEmptyString;
  547. }
  548. END_NCBI_SCOPE