2010-09-30 60 views
1

我從精神手冊擴展了Mini XML示例。
語法描述了一個xml標籤,它可以用'/>'關閉,並且沒有子節點,或者像例子中的關閉標籤''那樣關閉,並且可以有孩子。改進替代解析器的使用

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 
#include <boost/variant.hpp> 
#include <boost/variant/recursive_variant.hpp> 

struct XmlTree; 

typedef boost::variant<boost::recursive_wrapper<XmlTree>, std::string> 
    mini_xml_node; 

typedef std::vector<mini_xml_node> Children; 

struct XmlTree 
{ 
    std::string name; 
    Children childs; 
}; 

BOOST_FUSION_ADAPT_STRUCT(
XmlTree, 
(std::string, name) 
(Children, childs) 
) 

typedef std::string::const_iterator Iterator; 

namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 
namespace phoenix = boost::phoenix; 

class XmlParserGrammar : public qi::grammar<Iterator, XmlTree(), qi::locals<std::string*>, ascii::space_type> 
{ 
public: 
XmlParserGrammar() : XmlParserGrammar::base_type(xml, "xml") 
{ 
    using qi::lit; 
    using qi::lexeme; 
    using qi::attr; 
    using ascii::space; 
    using ascii::char_; 
    using ascii::alnum; 
    using phoenix::val; 

    xml %= 
     startTag[qi::_a = &qi::_1] >> 
     (
     (
      lit("/>") > attr(Children()) //can i remove this somehow? 
     ) 
     | 
     (
      lit(">") 
      >> *node_ 
      > endTag(*qi::_a) 
     ) 
     ); 

    startTag %= '<' >> !lit('/') >> lexeme[ +(alnum - (space | '>' | "/>")) ] ; 

    node_ %= xml | text; 

    endTag = "</" > lit(qi::_r1) > '>'; 

    text %= lexeme[+(char_ - '<')]; 
} 

private: 
    qi::rule<Iterator, XmlTree(), qi::locals<std::string*>, ascii::space_type> xml; 
    qi::rule<Iterator, std::string(), ascii::space_type> startTag; 
    qi::rule<Iterator, mini_xml_node(), ascii::space_type> node_; 
    qi::rule<Iterator, void(std::string&), ascii::space_type> endTag; 
    qi::rule<Iterator, std::string(), ascii::space_type> text; 
}; 

是否可以在沒有attr(Children())標籤的情況下編寫此規則?我認爲這或多或少是一種表現滯後。我需要它來避免替代解析器的可選屬性。 如果沒有子標籤,該屬性應該只是一個空向量。

回答

1

你應該能夠編寫:

xml %= startTag[_a = &_1] 
     >> attributes 
     >> ( "/>" >> eps 
      | ">" >> *node > endTag(*_a) 
     ) 
    ; 

剩下的矢量屬性不變(空)。

+0

對不起,但你的語法似乎不編譯。我認爲這是因爲(「/>」|「>」>> * node> endTag(* _ a))會生成一個可選屬性,但是我的'childs'成員不是可選的。我在問題中添加了xmlTree結構。 – MarcoH 2010-10-01 18:15:58

+0

我需要查看一個最小的自包含示例,以便能夠查看出了什麼問題。 – hkaiser 2010-10-01 22:29:06

+0

我在問題中添加了一個示例。它編譯VS 2008 – MarcoH 2010-10-02 16:23:39