提升::精神和语法

时间:2013-02-19 20:15:32

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

我试图简单地解析这个并用Boost :: Spirit来构建xml-minded结构,

One{
    Two{
        Three{
        }
    }
}

代码组织如下:

结构定义以保持精神:

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)
)

(从xml介绍中无耻窃取)

规则声明(在解析器类上)

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;

解析器'解析'方法中规则的定义。

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

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

_a和_1是boost :: phoenix变量。

此规则适用于上面粘贴的小剪裁,但如果我将其更改为:

One{
    Two{
    }
    Three{
    }
}

(同一范围内的两个组,而不是其他组内的组)解析器失败。 我不明白为什么。

1 个答案:

答案 0 :(得分:2)

为了将来参考,您的代码看起来像是Boost教程中的mini_xml2.cpp的简化版本(又名“无耻偷走的”)。

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

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

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

现在它已经很明显了:)每当解析器解析start_tag时,它就会开始寻找node s(因为>> *node部分)。由于}是合法的start_tag,因此可以将其识别为一个,但不应该。{/ p>


btw您可能会考虑修复代码中的一些冗余。例如:

在原始的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