c++ - 改进替代解析器的使用

标签 c++ boost boost-spirit boost-spirit-qi

我扩展了 spirit 手册中的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()) 标签的情况下编写此规则?我认为这或多或少是性能滞后。我需要它来避免替代解析器的可选属性。 如果没有子标签,该属性应该只是一个空 vector 。

最佳答案

你应该能够写:

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

这使 vector 属性保持不变(并且为空)。

关于c++ - 改进替代解析器的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3834489/

相关文章:

c++ - GetAsyncKeyState() defn 中的 "Shouldn' t be relied upon 是什么意思

c++ - 迁移工作模块时 Boost "is_virtual_base_of"编译错误

c++ - Boost.Chrono 与 Boost.Date_Time

python - 无法使用 MSVC2015 编译 boost.python 1.65.1

c++ - Boost Spirit 解析器在输入时崩溃

c++ - Boost spirit 将整数解析为自定义列表模板

android - 何时在 Android NDK 中使用 JNIEXPORT 和 JNICALL?

c++ - 在 C++ 中将字符串转换为 vector

c++ - 缺少模板参数

c++ - 是否有 boost::phoenix::at_c 结合 boost::spirit::qi::grammar 的替代方案