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 + -
显示快捷键?