summaryrefslogtreecommitdiff
path: root/boost/spirit/home/classic/tree/impl/tree_to_xml.ipp
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/spirit/home/classic/tree/impl/tree_to_xml.ipp
downloadboost-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.ipp526
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, '&', "&amp;", 3);
+ encode(str, '<', "&lt;", 2);
+ encode(str, '>', "&gt;", 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)