提升精神:如何将“从行到特定单词”的任何内容收集到一个变量中?

时间:2014-07-07 20:21:58

标签: c++ boost boost-spirit

我有以下字符串

   GOOSE BAY  LATITUDE   53.27    LONGITUDE   299.60    ALTITUDE    46 M

我需要使用Boost精神解析变量。

目前我的代码如下:

 qi::rule < string::const_iterator, std::string(), asc::space_type> any_string;
 any_string %= as_string [lexeme[+(asc::char_ - asc::space)]];
 r = phrase_parse(first, last,
                    (any_string[ph::ref(station) = _1] >> "LATITUDE" >> 
 double_[ph::ref(lat) = _1] >> "LONGITUDE" >> double_[ph::ref(lon) = _1] >> 
 "ALTITUDE" >> double_[ph::ref(alt) = _1] >> "M"), asc::space);

工作正常(即商店 电台 lat lon alt 变量)如果在“LATITUDE”之前,我只有一个字。

然而,我还需要在“LATITUDE”之前存储变量 station ,如果它是一个或几个(不仅仅是两个,如例子)单词。但它不能消耗任何后续的“LATITUDE”字,所以纬度等仍然是他们自己的变量。请帮助我找出正确的Boost Spirit表达式以识别 station 在行中看到的所有内容,包含的空格,最多为特殊单词(上例中的LATITUDE) )。

1 个答案:

答案 0 :(得分:4)

注意:

  • asc::graph相当于asc::char_ - asc::space
  • 如果您声明没有队长的规则,则
  • lexeme是多余的(另请参阅Boost spirit skipper issues

     qi::rule<It> any_string = +qi::graph_;
    
  • 在第一个字段中的每个字符处断言第一个关键字的否定匹配:

    +(qi::char_ - "LATITUDE")
    
  • 您可以传递对phrase_parse API的引用,这样您就可以不进行语义操作(另请参阅Boost Spirit: "Semantic actions are evil"?):

    bool r = qi::phrase_parse(first, last,
         ( qi::raw [ +(qi::char_ - "LATITUDE") ] >> "LATITUDE" >>
           qi::double_ >> "LONGITUDE" >> 
           qi::double_ >> "ALTITUDE" >> 
           qi::double_ >> "M"), 
        asc::space,
        name, lat, lon, alt);
    

查看 Live On Coliru

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;
namespace asc= boost::spirit::ascii;

int main()
{
    typedef std::string::const_iterator It;

    std::string const input("GOOSE BAY  LATITUDE   53.27    LONGITUDE   299.60    ALTITUDE    46 M");

    std::string name;
    double lat, lon, alt;

    It first(input.begin()), last(input.end());

    bool r = qi::phrase_parse(first, last,
            (qi::raw [ +(qi::char_ - "LATITUDE") ] >> "LATITUDE" >>
             qi::double_ >> "LONGITUDE" >> 
             qi::double_ >> "ALTITUDE" >> 
             qi::double_ >> "M"), 
            asc::space,
            name, lat, lon, alt);

    if (r)
        std::cout << "Parsed: '" << name << "' lat:" << lat << " lon:" << lon << " alt:" << alt << "\n";
    else
        std::cout << "Failed\n";

    if (first != last)
        std::cout << "Remaining input: '" << std::string(first, last) << "'\n";
}