解析交错线与提升精神

时间:2015-04-15 12:46:21

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

我是精神新手,目前正在尝试将一个类似ini的文件解析为一个结构。创建语法是可以的,但映射生成对我来说仍然是一种魔力。该文件如下所示:

[fine]
@cmp1
@cmp2
muh=b

[fail]
@cmp1
a=b
@cmp2

只要我有订购的要求和属性(#34;罚款"),它就可以工作但如果要求和属性是交错的,我就无法工作(第34节"失败&#34)。我的结构定义如下所示:

typedef std::map<std::string, std::string> Pairs;
struct Section
{
    std::string name;
    std::vector<std::string> requirements;
    Pairs properties;
};
BOOST_FUSION_ADAPT_STRUCT(
    Section, 
    (std::string, name)
    (std::vector<std::string>, requirements)
    (Pairs, properties)
)

我目前的语法如下:

template <typename Iterator, typename Skipper>
struct SectionParser : qi::grammar<Iterator, Section(), Skipper>
{
    qi::rule<Iterator, Section(), Skipper> section;
    qi::rule<Iterator, std::pair<std::string, std::string>(), Skipper> pair;
    qi::rule<Iterator, std::vector<std::string>()> requirements;
    qi::rule<Iterator, std::string()> key, value, sectionIdent, name, component;

    SectionParser() 
        : SectionParser::base_type(section, "entity grammar")
    {
        using namespace qi;

        sectionIdent = *(qi::char_ - (qi::lit('[') | qi::lit(']') | qi::eol));
        name = *qi::eol > qi::lit('[') > sectionIdent > qi::lit(']') > (qi::eol | qi::eoi);         

        component = qi::char_('@') > *(qi::char_ - (qi::eol)) > (qi::eol | qi::eoi);

        value = *(qi::char_ - (qi::eol | qi::eoi));
        key = qi::char_("a-zA-Z_") > *qi::char_("a-zA-Z_0-9");
        pair = key > qi::lit('=') > value > (qi::eol | qi::eoi);

        section = name >> *component >> *pair;
    }
};

这就是我如何运行解析器:

std::vector<Section> sections;
bool ok = phrase_parse(first, last, (sectionParser % +qi::eol) >> *qi::eol > qi::eoi, qi::blank, sections);

我也有这样的感觉,我使线条结束处理比应该更复杂......

1 个答案:

答案 0 :(得分:1)

阅读parsing into several vector members后,我发现只使用语义动作的解决方案。

结构定义保持不变:

struct Section
{
    std::string name;
    std::vector<std::string> requirements;
    Pairs properties;
};

不再使用adapt struct。

语法变为:

template <typename Iterator, typename Skipper>
struct SectionParser : qi::grammar<Iterator, Section(), Skipper>
{
    qi::rule<Iterator, Section(), Skipper> start;
    qi::rule<Iterator, std::string()> value, ident, name, component;
    qi::rule<Iterator, std::pair<std::string, std::string>()> pair;

    SectionParser() 
        : SectionParser::base_type(start, "section grammar")
    {
        auto add_component = phx::push_back(phx::bind(&Section::requirements, qi::_val), qi::_1);
        auto add_pair = phx::insert(phx::bind(&Section::properties, qi::_val), qi::_1);
        auto set_name = phx::assign(phx::bind(&Section::name, qi::_val), qi::_1);

        ident = +qi::char_("a-zA-Z0-9_");
        component = qi::char_('@') > ident >> (qi::eol | qi::eoi);
        value = *(qi::char_ - (qi::eol | qi::eoi));
        pair = ident > qi::lit('=') > value >> (qi::eol | qi::eoi);
        name = qi::lit('[') > ident > qi::lit(']') >> (qi::eol | qi::eoi);
        start = name[set_name] >> *(component[add_component] | pair[add_pair]);
    }
};