2015-04-15 82 views
2

我對精神很陌生,目前試圖將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); 

我也有我做的感覺行結束處理比它應該更復雜...

回答

1

看完後parsing into several vector members我發現了一個只使用語義動作的解決方案。

結構定義保持不變:

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