【问题标题】:parsing interleaved lines with boost spirit用增强精神解析交错行
【发布时间】:2015-04-15 12:46:20
【问题描述】:

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

[fine]
@cmp1
@cmp2
muh=b

[fail]
@cmp1
a=b
@cmp2

只要我有订购的要求和属性(“罚款”部分),它就可以工作,但如果要求和属性交错(“失败”部分),我无法让它工作。我的结构定义如下所示:

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

我也觉得我让行尾处理比它应该的更复杂......

【问题讨论】:

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


    【解决方案1】:

    阅读parsing into several vector members 后,我找到了一个仅使用语义操作的解决方案。

    结构定义保持不变:

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

    不要再使用adapter结构了。

    语法变为:

    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]);
        }
    };
    

    【讨论】:

      猜你喜欢
      • 2011-06-19
      • 2011-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      相关资源
      最近更新 更多