Question

J'étendu l'exemple XML Mini à partir du manuel d'esprit.
La grammaire décrit une balise xml qui peut être fermé avec « /> » et n'a pas de nœuds enfants ou qui est fermée comme dans l'exemple avec une étiquette de fermeture « » et peut éventuellement avoir des enfants.

#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;
};

Est-il possible d'écrire cette règle sans l'étiquette attr (Enfants ())? Je pense qu'il est plus ou moins un retard de performance. J'ai besoin pour éviter l'attribut facultatif de l'analyseur alternatif. S'il n'y a pas de balises enfant l'attribut ne doit être un vecteur vide.

Était-ce utile?

La solution

Vous devriez être capable d'écrire:

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

qui laisse l'attribut vecteur inchangé (et vide).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top