mini_xml_karma.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 221 行
CPP
221 行
/*============================================================================= Copyright (c) 2001-2008 Joel de Guzman Copyright (c) 2001-2008 Hartmut Kaiser Distributed under 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)=============================================================================*//////////////////////////////////////////////////////////////////////////////////// A mini XML-like parser, Karma is used to print out the generated AST//// [ JDG March 25, 2007 ] spirit2// [ HK April 02, 2007 ] spirit2/////////////////////////////////////////////////////////////////////////////////#include <boost/config/warning_disable.hpp>#include <boost/spirit/include/qi.hpp>#include <boost/spirit/include/karma.hpp>#include <boost/spirit/include/phoenix_core.hpp>#include <boost/spirit/include/phoenix_operator.hpp>#include <boost/spirit/include/phoenix_fusion.hpp>#include <boost/spirit/include/phoenix_function.hpp>#include <boost/spirit/include/phoenix_stl.hpp>#include <boost/fusion/include/adapt_struct.hpp>#include <boost/variant/recursive_variant.hpp>#include <iostream>#include <fstream>#include <string>#include <vector>using namespace boost::spirit;using namespace boost::spirit::ascii;using namespace boost::spirit::arg_names;namespace fusion = boost::fusion;namespace phoenix = boost::phoenix;using phoenix::at_c;using phoenix::push_back;///////////////////////////////////////////////////////////////////////////////// Our mini XML tree representation///////////////////////////////////////////////////////////////////////////////struct mini_xml;typedef boost::variant< boost::recursive_wrapper<mini_xml> , std::string >mini_xml_node;struct mini_xml{ std::string name; // tag name std::vector<mini_xml_node> children; // children};// We need to tell fusion about our mini_xml struct// to make it a first-class fusion citizenBOOST_FUSION_ADAPT_STRUCT( mini_xml, (std::string, name) (std::vector<mini_xml_node>, children))///////////////////////////////////////////////////////////////////////////////// Our mini XML grammar definition///////////////////////////////////////////////////////////////////////////////template <typename Iterator>struct mini_xml_parser : qi::grammar<Iterator, mini_xml(), space_type>{ mini_xml_parser() : mini_xml_parser::base_type(xml) { text = lexeme[+(char_ - '<') [_val += _1]]; node = (xml | text) [_val = _1]; start_tag = '<' >> lexeme[+(char_ - '>') [_val += _1]] >> '>' ; end_tag = "</" >> lit(_r1) >> '>' ; xml = start_tag [at_c<0>(_val) = _1] >> *node [push_back(at_c<1>(_val), _1)] >> end_tag(at_c<0>(_val)) ; } qi::rule<Iterator, mini_xml(), space_type> xml; qi::rule<Iterator, mini_xml_node(), space_type> node; qi::rule<Iterator, std::string(), space_type> text; qi::rule<Iterator, std::string(), space_type> start_tag; qi::rule<Iterator, void(std::string), space_type> end_tag;};///////////////////////////////////////////////////////////////////////////////// A couple of phoenix functions helping to access the elements of the // generated AST///////////////////////////////////////////////////////////////////////////////template <typename T>struct get_element{ template <typename T1> struct result { typedef T const& type; }; T const& operator()(mini_xml_node const& node) const { return boost::get<T>(node); }};phoenix::function<get_element<std::string> > _string;phoenix::function<get_element<mini_xml> > _xml;///////////////////////////////////////////////////////////////////////////////// The output grammar defining the format of the generated data///////////////////////////////////////////////////////////////////////////////template <typename OutputIterator>struct mini_xml_generator : karma::grammar<OutputIterator, mini_xml()>{ mini_xml_generator() : mini_xml_generator::base_type(xml) { node %= lit[_1 = _string(_r0)] | xml[_1 = _xml(_r0)] ; xml = char_('<') << lit(at_c<0>(_r0)) << '>' << (*node)[_1 = at_c<1>(_r0)] << lit("</") << lit(at_c<0>(_r0)) << '>' ; } karma::rule<OutputIterator, mini_xml()> xml; karma::rule<OutputIterator, mini_xml_node()> node;};///////////////////////////////////////////////////////////////////////////////// Main program///////////////////////////////////////////////////////////////////////////////int main(int argc, char **argv){ char const* filename; if (argc > 1) { filename = argv[1]; } else { std::cerr << "Error: No input file provided." << std::endl; return 1; } std::ifstream in(filename, std::ios_base::in); if (!in) { std::cerr << "Error: Could not open input file: " << filename << std::endl; return 1; } std::string storage; // We will read the contents here. in.unsetf(std::ios::skipws); // No white space skipping! std::copy( std::istream_iterator<char>(in), std::istream_iterator<char>(), std::back_inserter(storage)); typedef mini_xml_parser<std::string::const_iterator> mini_xml_parser; mini_xml_parser xmlin; // Our grammar definition mini_xml ast; // our tree std::string::const_iterator iter = storage.begin(); std::string::const_iterator end = storage.end(); bool r = qi::phrase_parse(iter, end, xmlin, ast, space); if (r && iter == end) { std::cout << "-------------------------\n"; std::cout << "Parsing succeeded\n"; std::cout << "-------------------------\n"; typedef std::back_insert_iterator<std::string> outiter_type; typedef mini_xml_generator<outiter_type> mini_xml_generator; mini_xml_generator xmlout; // Our grammar definition std::string generated; bool r = karma::generate(std::back_inserter(generated), xmlout, ast); if (r) std::cout << generated << std::endl; return 0; } else { std::string::const_iterator some = iter+30; std::string context(iter, (some>end)?end:some); std::cout << "-------------------------\n"; std::cout << "Parsing failed\n"; std::cout << "stopped at: \": " << context << "...\"\n"; std::cout << "-------------------------\n"; return 1; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?