2013-12-12 52 views
3

我赢得解析“text {<>}”之类的结构。例如,Spirit文档内容类似AST。 对于解析字符串,这样解析boost :: spirit递归结构

<tag1>text1<tag2>text2</tag1></tag2> 

此代码的工作:

templ  = (tree | text)  [_val = _1]; 

    start_tag = '<' 
      >> !lit('/') 
      >> lexeme[+(char_- '>') [_val += _1]] 
      >>'>'; 

    end_tag = "</" 
      >> string(_r1) 
      >> '>'; 

    tree = start_tag   [at_c<1>(_val) = _1] 
      >> *templ   [push_back(at_c<0>(_val), _1) ] 
      >> end_tag(at_c<1>(_val)) 
      ; 

为了解析字符串这样

<tag<tag>some_text> 

此代码不能工作:

templ  = (tree | text)  [_val = _1]; 


    tree = '<' 
      >> *templ   [push_back(at_c<0>(_val), _1) ] 
      >> '>' 
      ; 

TEMPL是平价用recursive_wrapper里面唱结构:

namespace client { 

    struct tmp; 

    typedef boost::variant < 
     boost::recursive_wrapper<tmp>, 
     std::string 
    > tmp_node; 

    struct tmp { 
    std::vector<tmp_node> content; 
    std::string text; 
    }; 
} 

BOOST_FUSION_ADAPT_STRUCT(
    tmp_view::tmp, 
    (std::vector<tmp_view::tmp_node>, content) 
    (std::string,text) 
) 

谁能解释它为什么会发生?也许谁知道类似的解析器写在boost :: spirit上?

+0

问题是什么?我看到两个无效的XML片段和两个相对不相关的语法,这两个语法显然都不应该解析无效的XML。我用Spirit编写了很多解析器。也许他们是相似的。但是你忘了提及“发生了什么”(所以我们不能说“为什么会发生”),而且你也忘了说你想要达到的目标。所以_who知道_有类似的解析器... – sehe

+0

我会忘记一个文本规则。在第二种情况下(工作)它必须是“text = lexeme [+(char_ - '<' - '>')[_val + = _1]];” – crastinus

回答

2

只是猜测,你实际上并没有想在所有的解析XML,而是某种分层文本混合内容的标记语言,我会做

 simple = +~qi::char_("><"); 
     nested = '<' >> *soup >> '>'; 
     soup = nested|simple; 

随着定义为AST /规则

typedef boost::make_recursive_variant< 
     boost::variant<std::string, std::vector<boost::recursive_variant_> > 
    >::type tag_soup; 

qi::rule<It, std::string()>   simple; 
qi::rule<It, std::vector<tag_soup>()> nested; 
qi::rule<It, tag_soup()>    soup; 

看到它Live On Coliru

//// #define BOOST_SPIRIT_DEBUG 
#include <boost/spirit/include/qi.hpp> 
#include <boost/variant/recursive_variant.hpp> 

#include <iostream> 
#include <fstream> 

namespace client 
{ 
    typedef boost::make_recursive_variant< 
      boost::variant<std::string, std::vector<boost::recursive_variant_> > 
     >::type tag_soup; 

    namespace qi = boost::spirit::qi; 

    template <typename It> 
    struct parser : qi::grammar<It, tag_soup()> 
    { 
     parser() : parser::base_type(soup) 
     { 
      simple = +~qi::char_("><"); 
      nested = '<' >> *soup >> '>'; 
      soup = nested|simple; 

      BOOST_SPIRIT_DEBUG_NODES((simple)(nested)(soup)) 
     } 
     private: 
     qi::rule<It, std::string()>   simple; 
     qi::rule<It, std::vector<tag_soup>()> nested; 
     qi::rule<It, tag_soup()>    soup; 
    }; 
} 

namespace boost { // leverage ADL on variant<> 
    static std::ostream& operator<<(std::ostream& os, std::vector<client::tag_soup> const& soup) 
    { 
     os << "<"; 
     std::copy(soup.begin(), soup.end(), std::ostream_iterator<client::tag_soup>(os)); 
     return os << ">"; 
    } 
} 

int main(int argc, char **argv) 
{ 
    if (argc < 2) { 
     std::cerr << "Error: No input file provided.\n"; 
     return 1; 
    } 

    std::ifstream in(argv[1]); 
    std::string const storage(std::istreambuf_iterator<char>(in), {}); // We will read the contents here. 

    if (!(in || in.eof())) { 
     std::cerr << "Error: Could not read from input file\n"; 
     return 1; 
    } 

    static const client::parser<std::string::const_iterator> p; 

    client::tag_soup ast; // Our tree 
    bool ok = parse(storage.begin(), storage.end(), p, ast); 

    if (ok) std::cout << "Parsing succeeded\nData: " << ast << "\n"; 
    else std::cout << "Parsing failed\n"; 

    return ok? 0 : 1; 
} 

如果您定义了BOOST_SPIRIT_DEBUG,您将得到解析过程的详细输出。

对于输入

<some text with nested <tags <etc...> >more text> 

打印

Parsing succeeded 
Data: <some text with nested <tags <etc...> >more text> 

注意,输出从所述变体,而不是原始文本打印。

+0

我会试着用DEBUG,谢谢。 – crastinus

+0

我放弃了解析器。如何使用多个标签类型('<','>')。例如“ text2 <>}>”。如何使用close标签('>','}')解析器知道什么标签打开表达式(在使用引用的mini_xml示例中)。 – crastinus

+0

@crastinus你仍然需要告诉我们你想达到的目标。即使没有使用Spirit,我也可以“解析”那些标签。 ('cat input.txt>/dev/null',也就是说,如果没有需要/需要的行为)。 – sehe