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())標籤的情況下編寫此規則?我認爲這或多或少是一種表現滯後。我需要它來避免替代解析器的可選屬性。 如果沒有子標籤,該屬性應該只是一個空向量。
對不起,但你的語法似乎不編譯。我認爲這是因爲(「/>」|「>」>> * node> endTag(* _ a))會生成一個可選屬性,但是我的'childs'成員不是可選的。我在問題中添加了xmlTree結構。 – MarcoH 2010-10-01 18:15:58
我需要查看一個最小的自包含示例,以便能夠查看出了什麼問題。 – hkaiser 2010-10-01 22:29:06
我在問題中添加了一個示例。它編譯VS 2008 – MarcoH 2010-10-02 16:23:39