diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
commit | 1a78a62555be32868418fe52f8e330c9d0f95d5a (patch) | |
tree | d3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/spirit/home/classic/tree/impl/tree_to_xml.ipp | |
download | boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2 boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip |
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/spirit/home/classic/tree/impl/tree_to_xml.ipp')
-rw-r--r-- | boost/spirit/home/classic/tree/impl/tree_to_xml.ipp | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/boost/spirit/home/classic/tree/impl/tree_to_xml.ipp b/boost/spirit/home/classic/tree/impl/tree_to_xml.ipp new file mode 100644 index 0000000000..2f0da8bf44 --- /dev/null +++ b/boost/spirit/home/classic/tree/impl/tree_to_xml.ipp @@ -0,0 +1,526 @@ +/*============================================================================= + Copyright (c) 2001-2008 Hartmut Kaiser + Copyright (c) 2001-2003 Daniel Nuffer + http://spirit.sourceforge.net/ + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +#if !defined(TREE_TO_XML_IPP) +#define TREE_TO_XML_IPP + +#include <cstdio> +#include <cstdarg> +#include <locale> +#include <string> +#include <cstring> + +#include <map> +#include <iostream> +#include <boost/config.hpp> +#include <boost/assert.hpp> + +#ifdef BOOST_NO_STRINGSTREAM +#include <strstream> +#define BOOST_SPIRIT_OSSTREAM std::ostrstream +inline +std::string BOOST_SPIRIT_GETSTRING(std::ostrstream& ss) +{ + ss << std::ends; + std::string rval = ss.str(); + ss.freeze(false); + return rval; +} +#else +#include <sstream> +#define BOOST_SPIRIT_GETSTRING(ss) ss.str() +#define BOOST_SPIRIT_OSSTREAM std::basic_ostringstream<CharT> +#endif + +namespace boost { namespace spirit { + +BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN + +namespace impl { + + /////////////////////////////////////////////////////////////////////////// + template <typename CharT> + struct string_lit; + + template <> + struct string_lit<char> + { + static char get(char c) { return c; } + static std::string get(char const* str = "") { return str; } + }; + + template <> + struct string_lit<wchar_t> + { + static wchar_t get(char c) + { + typedef std::ctype<wchar_t> ctype_t; + return std::use_facet<ctype_t>(std::locale()).widen(c); + } + static std::basic_string<wchar_t> get(char const* source = "") + { + using namespace std; // some systems have size_t in ns std + size_t len = strlen(source); + std::auto_ptr<wchar_t> result (new wchar_t[len+1]); + result.get()[len] = '\0'; + + // working with wide character streams is supported only if the + // platform provides the std::ctype<wchar_t> facet + BOOST_ASSERT(std::has_facet<std::ctype<wchar_t> >(std::locale())); + + std::use_facet<std::ctype<wchar_t> >(std::locale()) + .widen(source, source + len, result.get()); + return result.get(); + } + }; +} + +// xml formatting helper classes +namespace xml { + + template <typename CharT> + inline void + encode (std::basic_string<CharT> &str, char s, char const *r, int len) + { + typedef typename std::basic_string<CharT>::size_type size_type; + + size_type pos = 0; + while ((pos = str.find_first_of (impl::string_lit<CharT>::get(s), pos)) != + size_type(std::basic_string<CharT>::npos)) + { + str.replace (pos, 1, impl::string_lit<CharT>::get(r)); + pos += len; + } + } + + template <typename CharT> + inline std::basic_string<CharT> + encode (std::basic_string<CharT> str) + { + encode(str, '&', "&", 3); + encode(str, '<', "<", 2); + encode(str, '>', ">", 2); + encode(str, '\r', "\\r", 1); + encode(str, '\n', "\\n", 1); + return str; + } + + template <typename CharT> + inline std::basic_string<CharT> + encode (CharT const *text) + { + return encode (std::basic_string<CharT>(text)); + } + + // format a xml attribute + template <typename CharT> + struct attribute + { + attribute() + { + } + + attribute (std::basic_string<CharT> const& key_, + std::basic_string<CharT> const& value_) + : key (key_), value(value_) + { + } + + bool has_value() + { + return value.size() > 0; + } + + std::basic_string<CharT> key; + std::basic_string<CharT> value; + }; + + template <typename CharT> + inline std::basic_ostream<CharT>& + operator<< (std::basic_ostream<CharT> &ostrm, attribute<CharT> const &attr) + { + if (0 == attr.key.size()) + return ostrm; + ostrm << impl::string_lit<CharT>::get(" ") << encode(attr.key) + << impl::string_lit<CharT>::get("=\"") << encode(attr.value) + << impl::string_lit<CharT>::get("\""); + return ostrm; + } + + // output a xml element (base class, not used directly) + template <typename CharT> + class element + { + protected: + element(std::basic_ostream<CharT> &ostrm_, bool incr_indent_ = true) + : ostrm(ostrm_), incr_indent(incr_indent_) + { + if (incr_indent) ++get_indent(); + } + ~element() + { + if (incr_indent) --get_indent(); + } + + public: + void output_space () + { + for (int i = 0; i < get_indent(); i++) + ostrm << impl::string_lit<CharT>::get(" "); + } + + protected: + int &get_indent() + { + static int indent; + + return indent; + } + + std::basic_ostream<CharT> &ostrm; + bool incr_indent; + }; + + // a xml node + template <typename CharT> + class node : public element<CharT> + { + public: + node (std::basic_ostream<CharT> &ostrm_, + std::basic_string<CharT> const& tag_, attribute<CharT> &attr) + : element<CharT>(ostrm_), tag(tag_) + { + this->output_space(); + this->ostrm + << impl::string_lit<CharT>::get("<") << tag_ << attr + << impl::string_lit<CharT>::get(">\n"); + } + node (std::basic_ostream<CharT> &ostrm_, + std::basic_string<CharT> const& tag_) + : element<CharT>(ostrm_), tag(tag_) + { + this->output_space(); + this->ostrm + << impl::string_lit<CharT>::get("<") << tag_ + << impl::string_lit<CharT>::get(">\n"); + } + ~node() + { + this->output_space(); + this->ostrm + << impl::string_lit<CharT>::get("</") << tag + << impl::string_lit<CharT>::get(">\n"); + } + + private: + std::basic_string<CharT> tag; + }; + + template <typename CharT> + class text : public element<CharT> + { + public: + text (std::basic_ostream<CharT> &ostrm_, + std::basic_string<CharT> const& tag, + std::basic_string<CharT> const& textlit) + : element<CharT>(ostrm_) + { + this->output_space(); + this->ostrm + << impl::string_lit<CharT>::get("<") << tag + << impl::string_lit<CharT>::get(">") << encode(textlit) + << impl::string_lit<CharT>::get("</") << tag + << impl::string_lit<CharT>::get(">\n"); + } + + text (std::basic_ostream<CharT> &ostrm_, + std::basic_string<CharT> const& tag, + std::basic_string<CharT> const& textlit, + attribute<CharT> &attr) + : element<CharT>(ostrm_) + { + this->output_space(); + this->ostrm + << impl::string_lit<CharT>::get("<") << tag << attr + << impl::string_lit<CharT>::get(">") << encode(textlit) + << impl::string_lit<CharT>::get("</") << tag + << impl::string_lit<CharT>::get(">\n"); + } + + text (std::basic_ostream<CharT> &ostrm_, + std::basic_string<CharT> const& tag, + std::basic_string<CharT> const& textlit, + attribute<CharT> &attr1, attribute<CharT> &attr2) + : element<CharT>(ostrm_) + { + this->output_space(); + this->ostrm + << impl::string_lit<CharT>::get("<") << tag << attr1 << attr2 + << impl::string_lit<CharT>::get(">") << encode(textlit) + << impl::string_lit<CharT>::get("</") << tag + << impl::string_lit<CharT>::get(">\n"); + } + }; + + // a xml comment + template <typename CharT> + class comment : public element<CharT> + { + public: + comment (std::basic_ostream<CharT> &ostrm_, + std::basic_string<CharT> const& commentlit) + : element<CharT>(ostrm_, false) + { + if ('\0' != commentlit[0]) + { + this->output_space(); + this->ostrm << impl::string_lit<CharT>::get("<!-- ") + << encode(commentlit) + << impl::string_lit<CharT>::get(" -->\n"); + } + } + }; + + // a xml document + template <typename CharT> + class document : public element<CharT> + { + public: + document (std::basic_ostream<CharT> &ostrm_) + : element<CharT>(ostrm_) + { + this->get_indent() = -1; + this->ostrm << impl::string_lit<CharT>::get( + "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"); + } + + document (std::basic_ostream<CharT> &ostrm_, + std::basic_string<CharT> const& mainnode, + std::basic_string<CharT> const& dtd) + : element<CharT>(ostrm_) + { + this->get_indent() = -1; + this->ostrm << impl::string_lit<CharT>::get( + "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"); + + this->output_space(); + this->ostrm << impl::string_lit<CharT>::get("<!DOCTYPE ") << mainnode + << impl::string_lit<CharT>::get(" SYSTEM \"") << dtd + << impl::string_lit<CharT>::get("\">\n"); + } + ~document() + { + BOOST_SPIRIT_ASSERT(-1 == this->get_indent()); + } + }; + +} // end of namespace xml + +namespace impl { + + /////////////////////////////////////////////////////////////////////////// + // look up the rule name from the given parser_id + template <typename AssocContainerT> + inline typename AssocContainerT::value_type::second_type + get_rulename (AssocContainerT const &id_to_name_map, + BOOST_SPIRIT_CLASSIC_NS::parser_id const &id) + { + typename AssocContainerT::const_iterator it = id_to_name_map.find(id); + if (it != id_to_name_map.end()) + return (*it).second; + typedef typename AssocContainerT::value_type::second_type second_t; + return second_t(); + } + + // dump a parse tree as xml + template < + typename CharT, typename IteratorT, typename GetIdT, typename GetValueT + > + inline void + token_to_xml (std::basic_ostream<CharT> &ostrm, IteratorT const &it, + bool is_root, GetIdT const &get_token_id, GetValueT const &get_token_value) + { + BOOST_SPIRIT_OSSTREAM stream; + + stream << get_token_id(*it) << std::ends; + xml::attribute<CharT> token_id ( + impl::string_lit<CharT>::get("id"), + BOOST_SPIRIT_GETSTRING(stream).c_str()); + xml::attribute<CharT> is_root_attr ( + impl::string_lit<CharT>::get("is_root"), + impl::string_lit<CharT>::get(is_root ? "1" : "")); + xml::attribute<CharT> nil; + xml::text<CharT>(ostrm, + impl::string_lit<CharT>::get("token"), + get_token_value(*it).c_str(), + token_id, + is_root_attr.has_value() ? is_root_attr : nil); + } + + template < + typename CharT, typename TreeNodeT, typename AssocContainerT, + typename GetIdT, typename GetValueT + > + inline void + tree_node_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &node, + AssocContainerT const& id_to_name_map, GetIdT const &get_token_id, + GetValueT const &get_token_value) + { + typedef typename TreeNodeT::const_iterator node_iter_t; + typedef + typename TreeNodeT::value_type::parse_node_t::const_iterator_t + value_iter_t; + + xml::attribute<CharT> nil; + node_iter_t end = node.end(); + for (node_iter_t it = node.begin(); it != end; ++it) + { + // output a node + xml::attribute<CharT> id ( + impl::string_lit<CharT>::get("rule"), + get_rulename(id_to_name_map, (*it).value.id()).c_str()); + xml::node<CharT> currnode (ostrm, + impl::string_lit<CharT>::get("parsenode"), + (*it).value.id() != 0 && id.has_value() ? id : nil); + + // first dump the value + std::size_t cnt = std::distance((*it).value.begin(), (*it).value.end()); + + if (1 == cnt) + { + token_to_xml (ostrm, (*it).value.begin(), + (*it).value.is_root(), get_token_id, get_token_value); + } + else if (cnt > 1) + { + xml::node<CharT> value (ostrm, + impl::string_lit<CharT>::get("value")); + bool is_root = (*it).value.is_root(); + + value_iter_t val_end = (*it).value.end(); + for (value_iter_t val_it = (*it).value.begin(); + val_it != val_end; ++val_it) + { + token_to_xml (ostrm, val_it, is_root, get_token_id, + get_token_value); + } + } + tree_node_to_xml(ostrm, (*it).children, id_to_name_map, + get_token_id, get_token_value); // dump all subnodes + } + } + + template <typename CharT, typename TreeNodeT, typename AssocContainerT> + inline void + tree_node_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &node, + AssocContainerT const& id_to_name_map) + { + typedef typename TreeNodeT::const_iterator node_iter_t; + + xml::attribute<CharT> nil; + node_iter_t end = node.end(); + for (node_iter_t it = node.begin(); it != end; ++it) + { + // output a node + xml::attribute<CharT> id ( + impl::string_lit<CharT>::get("rule"), + get_rulename(id_to_name_map, (*it).value.id()).c_str()); + xml::node<CharT> currnode (ostrm, + impl::string_lit<CharT>::get("parsenode"), + (*it).value.id() != parser_id() && id.has_value() ? id : nil); + + // first dump the value + if ((*it).value.begin() != (*it).value.end()) + { + std::basic_string<CharT> tokens ((*it).value.begin(), (*it).value.end()); + + if (tokens.size() > 0) + { + // output all subtokens as one string (for better readability) + xml::attribute<CharT> is_root ( + impl::string_lit<CharT>::get("is_root"), + impl::string_lit<CharT>::get((*it).value.is_root() ? "1" : "")); + xml::text<CharT>(ostrm, + impl::string_lit<CharT>::get("value"), tokens.c_str(), + is_root.has_value() ? is_root : nil); + } + + } + // dump all subnodes + tree_node_to_xml(ostrm, (*it).children, id_to_name_map); + } + } + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// dump a parse tree as a xml stream (generic variant) +template < + typename CharT, typename TreeNodeT, typename AssocContainerT, + typename GetIdT, typename GetValueT +> +inline void +basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree, +std::basic_string<CharT> const &input_line, AssocContainerT const& id_to_name, + GetIdT const &get_token_id, GetValueT const &get_token_value) +{ + // generate xml dump + xml::document<CharT> doc (ostrm, + impl::string_lit<CharT>::get("parsetree"), + impl::string_lit<CharT>::get("parsetree.dtd")); + xml::comment<CharT> input (ostrm, input_line.c_str()); + xml::attribute<CharT> ver ( + impl::string_lit<CharT>::get("version"), + impl::string_lit<CharT>::get("1.0")); + xml::node<CharT> mainnode (ostrm, + impl::string_lit<CharT>::get("parsetree"), ver); + + impl::tree_node_to_xml (ostrm, tree, id_to_name, get_token_id, + get_token_value); +} + +// dump a parse tree as a xml steam (for character based parsers) +template <typename CharT, typename TreeNodeT, typename AssocContainerT> +inline void +basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree, + std::basic_string<CharT> const &input_line, + AssocContainerT const& id_to_name) +{ + // generate xml dump + xml::document<CharT> doc (ostrm, + impl::string_lit<CharT>::get("parsetree"), + impl::string_lit<CharT>::get("parsetree.dtd")); + xml::comment<CharT> input (ostrm, input_line.c_str()); + xml::attribute<CharT> ver ( + impl::string_lit<CharT>::get("version"), + impl::string_lit<CharT>::get("1.0")); + xml::node<CharT> mainnode (ostrm, + impl::string_lit<CharT>::get("parsetree"), ver); + + impl::tree_node_to_xml(ostrm, tree, id_to_name); +} + +template <typename CharT, typename TreeNodeT> +inline void +basic_tree_to_xml (std::basic_ostream<CharT> &ostrm, TreeNodeT const &tree, + std::basic_string<CharT> const &input_line) +{ + return basic_tree_to_xml<CharT>(ostrm, tree, input_line, + std::map<BOOST_SPIRIT_CLASSIC_NS::parser_id, std::basic_string<CharT> >()); +} + +BOOST_SPIRIT_CLASSIC_NAMESPACE_END + +}} // namespace boost::spirit + +#undef BOOST_SPIRIT_OSSTREAM +#undef BOOST_SPIRIT_GETSTRING + +#endif // !defined(PARSE_TREE_XML_HPP) |