2011-01-23 63 views
2

下面是一個示例代碼Plus操作如預期

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 

#include <iostream> 
#include <string> 

namespace qi = boost::spirit::qi; 

    template <typename Iterator> 
    struct input : qi::grammar<Iterator, unsigned()> 
    { 
     input() : input::base_type(start) 
     { 
      using qi::lit; 
      using qi::double_; 

      start = lit("ADD") 
          >> +(
            +lit(" ") 
            >> double_ 
            >> +lit(" ") 
            >> double_ 
           ); 
     } 

     qi::rule<Iterator, unsigned()> start; 
    }; 

int main() 
{ 

    input<std::string::const_iterator> input_parser; // Our grammar 
    std::string str = "ADD 1132.324 2342.234"; 
    unsigned result; 

    std::string::const_iterator iter = str.begin(); 
    std::string::const_iterator end = str.end(); 

    bool r = qi::parse(iter, end, input_parser, result); 

} 

我收到以下錯誤不起作用。

/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:201: instantiated from ‘boost::spirit::qi::rule& boost::spirit::qi::rule::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr&, const boost::proto::exprns_::expr&>, 1l>&, const boost::spirit::terminal&>, 2l>&, const boost::proto::exprns_::expr&>, 1l>&>, 2l>&, const boost::spirit::terminal&>, 2l>&>, 1l>&>, 2l>, Iterator = __gnu_cxx::__normal_iterator, std::allocator > >, T1 = unsigned int()(), T2 = boost::fusion::unused_type, T3 = boost::fusion::unused_type, T4 = boost::fusion::unused_type]’ mini.c++:34: instantiated from ‘input::input() [with Iterator = __gnu_cxx::__normal_iterator, std::allocator > >]’ mini.c++:49: instantiated from here /usr/local/include/boost/spirit/home/qi/operator/plus.hpp:62: error: no type named ‘type’ in ‘struct boost::spirit::traits::container_valueâ€

怪異的部分是,如果我使用減號( - )操作即

start = lit("ADD") 
          >> -(
            +lit(" ") 
            >> double_ 
            >> +lit(" ") 
            >> double_ 
           ); 

...它編譯完全沒有問題!

在gcc上編譯4.3.4。

回答

2

您的啓動規則公開的屬性爲unsigned,而plus-parser公開容納包裝元素屬性的容器類型。下面是從docs屬性傳播規則:

a: A --> +a: vector<A> 

(即,如果解析器a暴露A類型的屬性,解析器+a將暴露(標準)容器保持的A情況下,例如std::vector<A>)。

在你的情況下,嵌入式解析器公開double的。出於這個原因,你需要爲預期改變才能起作用代碼:

template <typename Iterator> 
struct input : qi::grammar<Iterator, std::vector<double>()> 
{ 
    input() : input::base_type(start) 
    { 
     using qi::lit; 
     using qi::double_; 
     start = lit("ADD") >> +(+lit(" ") >> double_ >> +lit(" ") >> double_); 
    } 

    qi::rule<Iterator, std::vector<double>()> start; 
}; 

int main() 
{ 
    input<std::string::const_iterator> input_parser; // Our grammar 
    std::string str = "ADD 1132.324 2342.234"; 

    std::vector<double> result; 
    std::string::const_iterator iter = str.begin(); 
    std::string::const_iterator end = str.end(); 
    bool r = qi::parse(iter, end, input_parser, result); 
} 

但不幸的是,事情並不像看起來那麼容易。當前版本的Spirit有一個阻止代碼工作的錯誤(即使即將發佈的Boost V1.46仍然會有這個錯誤,但它在SVN中繼中是固定的)。問題是,plus並沒有將嵌入式元素「扁平化」到提供的容器中,從而導致每次由上面的代碼解析的double都會丟失。

的解決方法是避免序列露出裏面加多於一個屬性:

start = lit("ADD") >> +(+lit(" ") >> double_); 

驗證之後該解析的元素的數目是偶數。

附註:您似乎想跳過輸入中元素之間的空白。這可以通過使用跳過解析器更容易實現:

template <typename Iterator> 
struct input : qi::grammar<Iterator, std::vector<double>(), qi::space_type> 
{ 
    input() : input::base_type(start) 
    { 
     using qi::lit; 
     using qi::double_; 
     start = lit("ADD") >> +double_; 
    } 

    qi::rule<Iterator, std::vector<double>(), qi::space_type> start; 
}; 

int main() 
{ 
    input<std::string::const_iterator> input_parser; // Our grammar 
    std::string str = "ADD 1132.324 2342.234"; 

    std::vector<double> result; 
    std::string::const_iterator iter = str.begin(); 
    std::string::const_iterator end = str.end(); 
    bool r = qi::phrase_parse(iter, end, input_parser, qi::space, result); 
} 

它同時規避了上述問題。

+0

謝謝。你的解決方案運行良好,我現在看到我做錯了什麼。我的實際語法是空格分隔,所以我不能跳過空格。 – 2011-01-24 07:47:58