0

I'm trying to parse this simply and consise xml-minded structure with Boost::Spirit,

One{
    Two{
        Three{
        }
    }
}

And the code is organized as follows:

Struct definition to keep the spirit-stuff:

struct config;
typedef boost::variant< boost::recursive_wrapper<config> , std::string > config_node;

struct config
{
    std::string name;
    std::vector<config_node> children; 
};


BOOST_FUSION_ADAPT_STRUCT(
    config,
    (std::string, name)
    (std::vector<config_node>, children)
)

( shameless stealed from the xml intro )

Declaration of the rules ( on the parser class )

qi::rule<Iterator, config(), qi::locals<std::string>, ascii::space_type> cfg;
qi::rule<Iterator, config_node(), ascii::space_type> node;
qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;

Definition of the rules, in the parser 'parse' method.

    node = cfg;
    start_tag =  +(char_ -'{') >> '{';
    end_tag = char_('}');

    cfg %=  start_tag[_a = _1]
        >>  *node
        >>  end_tag(_a);

_a and _1 are boost::phoenix variables.

This rules works for the small snipped pasted above, but if I change it to:

One{
    Two{
    }
    Three{
    }
}

( two groups in the same scope, instead of group inside of other group ) the parser fails. and I have no idea why.

4

1 回答 1

2

为了将来参考,您的代码似乎是 Boost 教程中mini_xml2.cpp的简化版本(又名“无耻被盗”)。

为了使您的示例正常工作,您必须更改该行:

start_tag =  +(char_ -'{') >> '{';

start_tag = +(char_ -'{' - '}') >> '{';

现在非常不言自明:) 每当解析器解析 astart_tag时,它就会开始寻找nodes (因为>> *node部分)。既然}是合法的start_tag,它可能被认为是合法的,它不应该被承认。


顺便说一句,您可能会考虑修复代码中的一些冗余。例如:

在最初的 mini_xml2.cpp 示例中,end_tag用作检查您关闭与打开的标签相同的标签的函数(因此签名void(std::string))。你会更好

cfg %=  start_tag[_a = _1]
>> *node
>> "}";

mini_xml2.cpp 示例中的节点是多态的,因此boost::variant与访问者一起使用。在您的示例中,这也是多余的。老实说,这让我想知道这条线

node = cfg

在编译期间没有引起任何问题,因为node有一个boost::variant类型。仅供参考,在原始示例中,这一行是:

node %= xml | text;

并且%=操作员正确地“猜测”了 RHS 的类型,因为|操作员将结果读取为boost::variant.

于 2013-02-19T22:38:01.540 回答