2012-07-16 36 views
1

我有一個語法規則,看起來像這樣禁用這種情況下,因爲語義 行動在那裏。儘管如此,我看到裏面 三元編譯錯誤()這表明_1的類型不是向量作爲我 所期望的,而它是:​​屬性兼容性不是由語義動作

vector< 
    variant<std::string, 
      fusion::vector2<utree, 
          fusion::vector2<long unsigned int, utree> 
          > 
      > 
     > 

這意味着,出於某種原因,語義操作沒有啓動!

任何暗示爲什麼會發生這種情況?

注:我粘貼一個最小化的例子在這裏展示的問題:

http://pastebin.com/rgiy2QBW

謝謝!

回答

3

編譯器抱怨的任務在ternaryImpl::operator()正文內,這意味着顯然語義操作確實起作用了!

現在,雖然SA正確地阻止自動屬性傳播(除非運算符%=用於規則分配),但而不是意味着原始解析器公開的類型奇蹟般地改變。

您在問題列表中的類型,準確地反映瞭解析表達式/運營商將返回的內容:

  • 或(|)解析成一個變種
  • 序列(>>)解析成fusion::vector2<...>等。

現在,這是我的簡單,最小的變化,將使這個編譯。訣竅在於,通過使用明確的屬性類型分割出的子分區,使得您的屬性分配工作。這可以讓Spirit爲你做屬性轉換。

struct Parser: public qi::grammar<Iterator, utree()> 
{ 
    template <typename Tokens> 
     Parser(const Tokens &toks): 
      Parser::base_type(expression) 
    { 
     chain = +(
      (
       toks.symbol 
       [ 
        _val = construct<utree::list_type>() 
        // some code here 
       ] 
      | (
        factor >> 
       +(
        toks.arrow >> factor 
        | toks.dot >> factor 
       ) 
       ) 
       [ 
        _val = construct<utree::list_type>() 
        // some code here 
       ] 
      ) >> toks.assign 
     ); 
     expression = factor 
      | (chain >> factor) [ _val = ternary(_1, _2) ] 
      ; 
    } 

    rule<Iterator, utree::list_type()> chain; 
    rule<Iterator, utree()> expression, factor, test; 
}; 

注意如果你想你應該能夠做同樣沒有額外的規則定義(使用qi::attr_cast<>qi::as<>例如),但我懷疑這將是可讀/維護。

PS。類似的點可以從calc_utree_naive.cpp中拿走,它必然會使用比使用SA的calc_utree_ast.cpp版本更明確的規則屬性類型。

下面是完整的,編譯版本,與一些在線筆記註釋:

// #define BOOST_SPIRIT_USE_PHOENIX_V3 
// #define BOOST_RESULT_OF_USE_DECLTYPE 
#include <algorithm> 
#include <string> 
#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/support_utree.hpp> 
#include <boost/spirit/include/phoenix_function.hpp> 
#include <boost/spirit/include/phoenix_object.hpp> 
#include <boost/spirit/include/phoenix_stl.hpp> 

namespace lex = boost::spirit::lex; 
namespace qi  = boost::spirit::qi; 
namespace spirit = boost::spirit; 
namespace phx = boost::phoenix; 

using lex::token_def; 
using qi::rule; 
using qi::_1; 
using qi::_2; 
using qi::_val; 
using spirit::utree; 
using phx::construct; 

// base iterator type 
typedef std::string::iterator BaseIteratorT; 

// token type 
typedef lex::lexertl::token<BaseIteratorT, boost::mpl::vector</*double, int, */std::string> > TokenT; 

// lexer type 
typedef lex::lexertl::actor_lexer<TokenT> LexerT; 

template <typename LexerT> 
struct Tokens: public lex::lexer<LexerT> 
{ 
    Tokens() 
    { 
     using lex::_pass; 
     using lex::pass_flags; 

     // literals 
     symbol = "[a-zA-Z_?](\\w|\\?)*|@(\\w|\\?)+"; 
     arrow = "->"; 
     dot = '.'; 
     assign = "="; 

     // literal rules 
     this->self += symbol; 
     this->self += arrow; 
     this->self += dot; 
     this->self += assign; 
    } 

    ~Tokens() {} 

    // literal tokens 
    token_def<std::string> symbol; 
    token_def<> arrow, dot; // HINT: lex::omit here? 
    /* 
    *^Otherwise, expect these to be all exposed as Qi attributes as well, so 
    * _1, _2, _3, _4 a bit more than you'd expect 
    */ 
    token_def<lex::omit> assign; 
}; 

struct ternaryImpl 
{ 
    template <typename Expr1Type, typename Expr2Type> 
    struct result { typedef utree type; }; 

    template <typename Expr1Type, typename Expr2Type> 
    utree operator()(Expr1Type &vec, Expr2Type &operand) const { 
     utree ret; 

     for (typename Expr1Type::iterator it = vec.begin(); it != vec.end(); ++it) { 
     // some code 
     ret = *it; 
     // more code 
     } 

     // some code here 

     return ret; 
    } 
}; 

phx::function<ternaryImpl> ternary = ternaryImpl(); 

template <typename Iterator> 
struct Parser: public qi::grammar<Iterator, utree()> 
{ 
    template <typename Tokens> 
     Parser(const Tokens &toks): 
      Parser::base_type(expression) 
    { 
     chain = +(
      (
       toks.symbol 
       [ 
        _val = construct<utree::list_type>() 
        // some code here 
       ] 
      | (
        factor >> 
       +(
        toks.arrow >> factor 
        | toks.dot >> factor 
       ) 
       ) 
       [ 
        _val = construct<utree::list_type>() 
        // some code here 
       ] 
      ) >> toks.assign 
     ); 
     expression = factor 
      | (chain >> factor) [ _val = ternary(_1, _2) ] 
      ; 
    } 

    rule<Iterator, utree::list_type()> chain; 
    rule<Iterator, utree()> expression, factor, test; 
}; 

int main() 
{ 
    typedef Tokens<LexerT>::iterator_type IteratorT; 

    Tokens<LexerT> l; 
    Parser<IteratorT> p(l); 
} 
+0

謝謝!這對我有效。 – 2012-07-17 17:45:34