Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:02:06

0001 /*=============================================================================
0002     Copyright (c) 2001-2008 Hartmut Kaiser
0003     Copyright (c) 2001-2003 Daniel Nuffer
0004     http://spirit.sourceforge.net/
0005 
0006     Use, modification and distribution is subject to the Boost Software
0007     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0008     http://www.boost.org/LICENSE_1_0.txt)
0009 =============================================================================*/
0010 
0011 #ifndef BOOST_SPIRIT_CLASSIC_TREE_IMPL_TREE_TO_XML_IPP
0012 #define BOOST_SPIRIT_CLASSIC_TREE_IMPL_TREE_TO_XML_IPP
0013 
0014 #include <cstdio>
0015 #include <cstdarg>
0016 #include <locale>
0017 #include <string>
0018 #include <cstring>
0019 
0020 #include <map>
0021 #include <iostream>
0022 #include <boost/config.hpp>
0023 #include <boost/assert.hpp>
0024 #include <boost/scoped_array.hpp>
0025 
0026 #ifdef BOOST_NO_STRINGSTREAM
0027 #include <strstream>
0028 #define BOOST_SPIRIT_OSSTREAM std::ostrstream
0029 inline
0030 std::string BOOST_SPIRIT_GETSTRING(std::ostrstream& ss)
0031 {
0032     ss << std::ends;
0033     std::string rval = ss.str();
0034     ss.freeze(false);
0035     return rval;
0036 }
0037 #else
0038 #include <sstream>
0039 #define BOOST_SPIRIT_GETSTRING(ss) ss.str()
0040 #define BOOST_SPIRIT_OSSTREAM std::basic_ostringstream<CharT>
0041 #endif
0042 
0043 namespace boost { namespace spirit {
0044 
0045 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
0046 
0047 namespace impl {
0048 
0049     ///////////////////////////////////////////////////////////////////////////
0050     template <typename CharT>
0051     struct string_lit;
0052 
0053     template <>
0054     struct string_lit<char>
0055     {
0056         static char get(char c) { return c; }
0057         static std::string get(char const* str = "") { return str; }
0058     };
0059 
0060     template <>
0061     struct string_lit<wchar_t>
0062     {
0063         static wchar_t get(char c)
0064         {
0065             typedef std::ctype<wchar_t> ctype_t;
0066             return std::use_facet<ctype_t>(std::locale()).widen(c);
0067         }
0068         static std::basic_string<wchar_t> get(char const* source = "")
0069         {
0070             using namespace std;        // some systems have size_t in ns std
0071             size_t len = strlen(source);
0072             boost::scoped_array<wchar_t> result (new wchar_t[len+1]);
0073             result.get()[len] = '\0';
0074 
0075             // working with wide character streams is supported only if the
0076             // platform provides the std::ctype<wchar_t> facet
0077             BOOST_ASSERT(std::has_facet<std::ctype<wchar_t> >(std::locale()));
0078 
0079             std::use_facet<std::ctype<wchar_t> >(std::locale())
0080                 .widen(source, source + len, result.get());
0081             return result.get();
0082         }
0083     };
0084 }
0085 
0086 // xml formatting helper classes
0087 namespace xml {
0088 
0089     template <typename CharT>
0090     inline void
0091     encode (std::basic_string<CharT> &str, char s, char const *r, int len)
0092     {
0093         typedef typename std::basic_string<CharT>::size_type size_type;
0094 
0095         size_type pos = 0;
0096         while ((pos = str.find_first_of (impl::string_lit<CharT>::get(s), pos)) !=
0097                 size_type(std::basic_string<CharT>::npos))
0098         {
0099             str.replace (pos, 1, impl::string_lit<CharT>::get(r));
0100             pos += len;
0101         }
0102     }
0103 
0104     template <typename CharT>
0105     inline std::basic_string<CharT>
0106     encode (std::basic_string<CharT> str)
0107     {
0108         encode(str, '&', "&amp;", 3);
0109         encode(str, '<', "&lt;", 2);
0110         encode(str, '>', "&gt;", 2);
0111         encode(str, '\r', "\\r", 1);
0112         encode(str, '\n', "\\n", 1);
0113         return str;
0114     }
0115 
0116     template <typename CharT>
0117     inline std::basic_string<CharT>
0118     encode (CharT const *text)
0119     {
0120         return encode (std::basic_string<CharT>(text));
0121     }
0122 
0123     // format a xml attribute
0124     template <typename CharT>
0125     struct attribute
0126     {
0127         attribute()
0128         {
0129         }
0130 
0131         attribute (std::basic_string<CharT> const& key_,
0132                    std::basic_string<CharT> const& value_)
0133           : key (key_), value(value_)
0134         {
0135         }
0136 
0137         bool has_value()
0138         {
0139             return value.size() > 0;
0140         }
0141 
0142         std::basic_string<CharT> key;
0143         std::basic_string<CharT> value;
0144     };
0145 
0146     template <typename CharT>
0147     inline std::basic_ostream<CharT>&
0148     operator<< (std::basic_ostream<CharT> &ostrm, attribute<CharT> const &attr)
0149     {
0150         if (0 == attr.key.size())
0151             return ostrm;
0152         ostrm << impl::string_lit<CharT>::get(" ") << encode(attr.key)
0153               << impl::string_lit<CharT>::get("=\"") << encode(attr.value)
0154               << impl::string_lit<CharT>::get("\"");
0155         return ostrm;
0156     }
0157 
0158     // output a xml element (base class, not used directly)
0159     template <typename CharT>
0160     class element
0161     {
0162     protected:
0163         element(std::basic_ostream<CharT> &ostrm_, bool incr_indent_ = true)
0164         :   ostrm(ostrm_), incr_indent(incr_indent_)
0165         {
0166             if (incr_indent) ++get_indent();
0167         }
0168         ~element()
0169         {
0170             if (incr_indent) --get_indent();
0171         }
0172 
0173     public:
0174         void output_space ()
0175         {
0176             for (int i = 0; i < get_indent(); i++)
0177                 ostrm << impl::string_lit<CharT>::get("    ");
0178         }
0179 
0180     protected:
0181         int &get_indent()
0182         {
0183             static int indent;
0184 
0185             return indent;
0186         }
0187 
0188         std::basic_ostream<CharT> &ostrm;
0189         bool incr_indent;
0190     };
0191 
0192     // a xml node
0193     template <typename CharT>
0194     class node : public element<CharT>
0195     {
0196     public:
0197         node (std::basic_ostream<CharT> &ostrm_,
0198               std::basic_string<CharT> const& tag_, attribute<CharT> &attr)
0199         :   element<CharT>(ostrm_), tag(tag_)
0200         {
0201             this->output_space();
0202             this->ostrm
0203                   << impl::string_lit<CharT>::get("<") << tag_ << attr
0204                   << impl::string_lit<CharT>::get(">\n");
0205         }
0206         node (std::basic_ostream<CharT> &ostrm_,
0207               std::basic_string<CharT> const& tag_)
0208         :   element<CharT>(ostrm_), tag(tag_)
0209         {
0210             this->output_space();
0211             this->ostrm
0212                   << impl::string_lit<CharT>::get("<") << tag_
0213                   << impl::string_lit<CharT>::get(">\n");
0214         }
0215         ~node()
0216         {
0217             this->output_space();
0218             this->ostrm
0219                   << impl::string_lit<CharT>::get("</") << tag
0220                   << impl::string_lit<CharT>::get(">\n");
0221         }
0222 
0223     private:
0224         std::basic_string<CharT> tag;
0225     };
0226 
0227     template <typename CharT>
0228     class text : public element<CharT>
0229     {
0230     public:
0231         text (std::basic_ostream<CharT> &ostrm_,
0232               std::basic_string<CharT> const& tag,
0233               std::basic_string<CharT> const& textlit)
0234         :   element<CharT>(ostrm_)
0235         {
0236             this->output_space();
0237             this->ostrm
0238                   << impl::string_lit<CharT>::get("<") << tag
0239                   << impl::string_lit<CharT>::get(">") << encode(textlit)
0240                   << impl::string_lit<CharT>::get("</") << tag
0241                   << impl::string_lit<CharT>::get(">\n");
0242         }
0243 
0244         text (std::basic_ostream<CharT> &ostrm_,
0245               std::basic_string<CharT> const& tag,
0246               std::basic_string<CharT> const& textlit,
0247               attribute<CharT> &attr)
0248         :   element<CharT>(ostrm_)
0249         {
0250             this->output_space();
0251             this->ostrm
0252                   << impl::string_lit<CharT>::get("<") << tag << attr
0253                   << impl::string_lit<CharT>::get(">") << encode(textlit)
0254                   << impl::string_lit<CharT>::get("</") << tag
0255                   << impl::string_lit<CharT>::get(">\n");
0256         }
0257 
0258         text (std::basic_ostream<CharT> &ostrm_,
0259               std::basic_string<CharT> const& tag,
0260               std::basic_string<CharT> const& textlit,
0261               attribute<CharT> &attr1, attribute<CharT> &attr2)
0262         :   element<CharT>(ostrm_)
0263         {
0264             this->output_space();
0265             this->ostrm
0266                   << impl::string_lit<CharT>::get("<") << tag << attr1 << attr2
0267                   << impl::string_lit<CharT>::get(">") << encode(textlit)
0268                   << impl::string_lit<CharT>::get("</") << tag
0269                   << impl::string_lit<CharT>::get(">\n");
0270         }
0271     };
0272 
0273     // a xml comment
0274     template <typename CharT>
0275     class comment : public element<CharT>
0276     {
0277     public:
0278         comment (std::basic_ostream<CharT> &ostrm_,
0279                  std::basic_string<CharT> const& commentlit)
0280         :   element<CharT>(ostrm_, false)
0281         {
0282             if ('\0' != commentlit[0])
0283             {
0284                 this->output_space();
0285                 this->ostrm << impl::string_lit<CharT>::get("<!-- ")
0286                       << encode(commentlit)
0287                       << impl::string_lit<CharT>::get(" -->\n");
0288             }
0289         }
0290     };
0291 
0292     // a xml document
0293     template <typename CharT>
0294     class document : public element<CharT>
0295     {
0296     public:
0297         document (std::basic_ostream<CharT> &ostrm_)
0298         :   element<CharT>(ostrm_)
0299         {
0300             this->get_indent() = -1;
0301             this->ostrm << impl::string_lit<CharT>::get(
0302                 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
0303         }
0304 
0305         document (std::basic_ostream<CharT> &ostrm_,
0306                   std::basic_string<CharT> const& mainnode,
0307                   std::basic_string<CharT> const& dtd)
0308         :   element<CharT>(ostrm_)
0309         {
0310             this->get_indent() = -1;
0311             this->ostrm << impl::string_lit<CharT>::get(
0312                 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
0313 
0314             this->output_space();
0315             this->ostrm << impl::string_lit<CharT>::get("<!DOCTYPE ") << mainnode
0316                   << impl::string_lit<CharT>::get(" SYSTEM \"") << dtd
0317                   << impl::string_lit<CharT>::get("\">\n");
0318         }
0319         ~document()
0320         {
0321             BOOST_SPIRIT_ASSERT(-1 == this->get_indent());
0322         }
0323     };
0324 
0325 } // end of namespace xml
0326 
0327 namespace impl {
0328 
0329     ///////////////////////////////////////////////////////////////////////////
0330     // look up the rule name from the given parser_id
0331     template <typename AssocContainerT>
0332     inline typename AssocContainerT::value_type::second_type
0333     get_rulename (AssocContainerT const &id_to_name_map,
0334         BOOST_SPIRIT_CLASSIC_NS::parser_id const &id)
0335     {
0336         typename AssocContainerT::const_iterator it = id_to_name_map.find(id);
0337         if (it != id_to_name_map.end())
0338             return (*it).second;
0339         typedef typename AssocContainerT::value_type::second_type second_t;
0340         return second_t();
0341     }
0342 
0343     // dump a parse tree as xml
0344     template <
0345         typename CharT, typename IteratorT, typename GetIdT, typename GetValueT
0346     >
0347     inline void
0348     token_to_xml (std::basic_ostream<CharT> &ostrm, IteratorT const &it,
0349         bool is_root, GetIdT const &get_token_id, GetValueT const &get_token_value)
0350     {
0351         BOOST_SPIRIT_OSSTREAM stream;
0352 
0353         stream << get_token_id(*it) << std::ends;
0354         xml::attribute<CharT> token_id (
0355                 impl::string_lit<CharT>::get("id"),
0356                 BOOST_SPIRIT_GETSTRING(stream).c_str());
0357         xml::attribute<CharT> is_root_attr (
0358                 impl::string_lit<CharT>::get("is_root"),
0359                 impl::string_lit<CharT>::get(is_root ? "1" : ""));
0360         xml::attribute<CharT> nil;
0361         xml::text<CharT>(ostrm,
0362                 impl::string_lit<CharT>::get("token"),
0363                 get_token_value(*it).c_str(),
0364                 token_id,
0365                 is_root_attr.has_value() ? is_root_attr : nil);
0366     }
0367 
0368     template <
0369         typename CharT, typename TreeNodeT, typename AssocContainerT,
0370         typename GetIdT, typename GetValueT
0371     >
0372     inline void
0373     tree_node_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &node,
0374         AssocContainerT const& id_to_name_map, GetIdT const &get_token_id,
0375         GetValueT const &get_token_value)
0376     {
0377         typedef typename TreeNodeT::const_iterator node_iter_t;
0378         typedef
0379             typename TreeNodeT::value_type::parse_node_t::const_iterator_t
0380             value_iter_t;
0381 
0382         xml::attribute<CharT> nil;
0383         node_iter_t end = node.end();
0384         for (node_iter_t it = node.begin(); it != end; ++it)
0385         {
0386             // output a node
0387             xml::attribute<CharT> id (
0388                 impl::string_lit<CharT>::get("rule"),
0389                 get_rulename(id_to_name_map, (*it).value.id()).c_str());
0390             xml::node<CharT> currnode (ostrm,
0391                 impl::string_lit<CharT>::get("parsenode"),
0392                 (*it).value.id() != 0 && id.has_value() ? id : nil);
0393 
0394             // first dump the value
0395             std::size_t cnt = std::distance((*it).value.begin(), (*it).value.end());
0396 
0397             if (1 == cnt)
0398             {
0399                 token_to_xml (ostrm, (*it).value.begin(),
0400                     (*it).value.is_root(), get_token_id, get_token_value);
0401             }
0402             else if (cnt > 1)
0403             {
0404                 xml::node<CharT> value (ostrm,
0405                         impl::string_lit<CharT>::get("value"));
0406                 bool is_root = (*it).value.is_root();
0407 
0408                 value_iter_t val_end = (*it).value.end();
0409                 for (value_iter_t val_it = (*it).value.begin();
0410                 val_it != val_end; ++val_it)
0411                 {
0412                     token_to_xml (ostrm, val_it, is_root, get_token_id,
0413                         get_token_value);
0414                 }
0415             }
0416             tree_node_to_xml(ostrm, (*it).children, id_to_name_map,
0417                 get_token_id, get_token_value);      // dump all subnodes
0418         }
0419     }
0420 
0421     template <typename CharT, typename TreeNodeT, typename AssocContainerT>
0422     inline void
0423     tree_node_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &node,
0424             AssocContainerT const& id_to_name_map)
0425     {
0426         typedef typename TreeNodeT::const_iterator node_iter_t;
0427 
0428         xml::attribute<CharT> nil;
0429         node_iter_t end = node.end();
0430         for (node_iter_t it = node.begin(); it != end; ++it)
0431         {
0432             // output a node
0433             xml::attribute<CharT> id (
0434                 impl::string_lit<CharT>::get("rule"),
0435                 get_rulename(id_to_name_map, (*it).value.id()).c_str());
0436             xml::node<CharT> currnode (ostrm,
0437                 impl::string_lit<CharT>::get("parsenode"),
0438                 (*it).value.id() != parser_id() && id.has_value() ? id : nil);
0439 
0440             // first dump the value
0441             if ((*it).value.begin() != (*it).value.end())
0442             {
0443                 std::basic_string<CharT> tokens ((*it).value.begin(), (*it).value.end());
0444 
0445                 if (tokens.size() > 0)
0446                 {
0447                     // output all subtokens as one string (for better readability)
0448                     xml::attribute<CharT> is_root (
0449                         impl::string_lit<CharT>::get("is_root"),
0450                         impl::string_lit<CharT>::get((*it).value.is_root() ? "1" : ""));
0451                     xml::text<CharT>(ostrm,
0452                         impl::string_lit<CharT>::get("value"), tokens.c_str(),
0453                         is_root.has_value() ? is_root : nil);
0454                 }
0455 
0456             }
0457             // dump all subnodes
0458             tree_node_to_xml(ostrm, (*it).children, id_to_name_map);
0459         }
0460     }
0461 
0462 } // namespace impl
0463 
0464 ///////////////////////////////////////////////////////////////////////////////
0465 // dump a parse tree as a xml stream (generic variant)
0466 template <
0467     typename CharT, typename TreeNodeT, typename AssocContainerT,
0468     typename GetIdT, typename GetValueT
0469 >
0470 inline void
0471 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
0472 std::basic_string<CharT> const &input_line, AssocContainerT const& id_to_name,
0473         GetIdT const &get_token_id, GetValueT const &get_token_value)
0474 {
0475     // generate xml dump
0476     xml::document<CharT> doc (ostrm,
0477             impl::string_lit<CharT>::get("parsetree"),
0478             impl::string_lit<CharT>::get("parsetree.dtd"));
0479     xml::comment<CharT> input (ostrm, input_line.c_str());
0480     xml::attribute<CharT> ver (
0481             impl::string_lit<CharT>::get("version"),
0482             impl::string_lit<CharT>::get("1.0"));
0483     xml::node<CharT> mainnode (ostrm,
0484             impl::string_lit<CharT>::get("parsetree"), ver);
0485 
0486     impl::tree_node_to_xml (ostrm, tree, id_to_name, get_token_id,
0487         get_token_value);
0488 }
0489 
0490 // dump a parse tree as a xml steam (for character based parsers)
0491 template <typename CharT, typename TreeNodeT, typename AssocContainerT>
0492 inline void
0493 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
0494         std::basic_string<CharT> const &input_line,
0495         AssocContainerT const& id_to_name)
0496 {
0497     // generate xml dump
0498     xml::document<CharT> doc (ostrm,
0499             impl::string_lit<CharT>::get("parsetree"),
0500             impl::string_lit<CharT>::get("parsetree.dtd"));
0501     xml::comment<CharT> input (ostrm, input_line.c_str());
0502     xml::attribute<CharT> ver (
0503             impl::string_lit<CharT>::get("version"),
0504             impl::string_lit<CharT>::get("1.0"));
0505     xml::node<CharT> mainnode (ostrm,
0506             impl::string_lit<CharT>::get("parsetree"), ver);
0507 
0508     impl::tree_node_to_xml(ostrm, tree, id_to_name);
0509 }
0510 
0511 template <typename CharT, typename TreeNodeT>
0512 inline void
0513 basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree,
0514         std::basic_string<CharT> const &input_line)
0515 {
0516     return basic_tree_to_xml<CharT>(ostrm, tree, input_line,
0517         std::map<BOOST_SPIRIT_CLASSIC_NS::parser_id, std::basic_string<CharT> >());
0518 }
0519 
0520 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
0521 
0522 }} // namespace boost::spirit
0523 
0524 #undef BOOST_SPIRIT_OSSTREAM
0525 #undef BOOST_SPIRIT_GETSTRING
0526 
0527 #endif