boost qi属性即将出现为qi :: unused_type

时间:2015-09-25 10:13:53

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

无法弄清楚为什么这条规则unary_msg不起作用,它说属性类型为qi::unused_type,但这对我没有意义。为什么这样的压力会折磨我?

template<class It, class Skip= boost::spirit::ascii::space_type>
struct g3: qi::grammar<It, ast::expr(), Skip>
{
  template<typename...Args>
  using R = qi::rule<It, Args...>;

  R<ast::expr(), Skip> start, expr_, term_, unary_term;
  R<ast::intlit()> int_;
  R<std::string()> selector_;
  R<boost::fusion::vector<ast::expr, std::vector<std::string>>, Skip> unary_msg;

  g3(): g3::base_type(start)
  {
    namespace ph = boost::phoenix;
    using namespace boost::spirit::qi;

    int_ = qi::int_;
    selector_ = lexeme[+qi::alnum];

    term_ = int_;
    unary_msg = term_ >> *selector_;
    unary_term = unary_msg[ qi::_val = ph::bind(&collect_unary, qi::_1) ];
    expr_ = unary_term;

    start = expr_;
  }
};

完整代码:http://coliru.stacked-crooked.com/a/e9afef4585ce76c3

1 个答案:

答案 0 :(得分:1)

与cv_and_he提及一样,添加parens。

包含许多清理建议的工作示例:

<强> Live On Coliru

注释

  1. 请勿在顶层使用std
  2. 不使用冲突的命名空间(使用boostfusion::vector很可能会导致意外或冲突)
  3. 不要使用ast::expr collect_unary (const boost::fusion::vector<ast::expr, std::vector<std::string>>& parts) //ast::expr collect_unary (const ast::expr& a, const std::vector<std::string>& msgs) { ast::expr res = boost::fusion::at_c<0>(parts);//a; const auto& msgs = boost::fusion::at_c<1>(parts); for(const auto& m: msgs) { ast::message msg; msg.name = m; msg.args.push_back(res); res = msg; } return res; }
  4. 等内部属性类型
  5. 使用现代风格BOOST_FUSION_ADAPT_STRUCT

  6. 一些小问题

  7. 例如以下功能

    ast::expr collect_unary(ast::expr accum, const std::vector<std::string>& msgs) {
        for (const auto &m : msgs)
            accum = ast::message { m, { accum } };
        return accum;
    }
    

    改为:

    #define BOOST_SPIRIT_USE_PHOENIX_V3
    #include <iostream>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    namespace qi = boost::spirit::qi;
    
    namespace ast {
        struct intlit {
            int value;
    
            intlit(int i = 0) : value(i) { } 
            intlit(intlit const&other) = default;
        };
    
        struct nil {};
        struct message;
    
        using expr = boost::make_recursive_variant<nil, intlit, message>::type;
    
        struct message {
            std::string name;
            std::vector<ast::expr> args;
        };
    }
    
    #include <boost/fusion/include/adapt_struct.hpp>
    
    BOOST_FUSION_ADAPT_STRUCT(ast::intlit, value)
    BOOST_FUSION_ADAPT_STRUCT(ast::message, name, args)
    
    struct ast_print {
        void operator()(ast::nil &) const     { std::cout << "nil"; }
        void operator()(ast::intlit &i) const { std::cout << i.value; }
        void operator()(ast::message &m) const {
            std::cout << "(" << m.name;
            for (auto &it : m.args) {
                std::cout << " ";
                boost::apply_visitor(ast_print(), it);
            }
            std::cout << ")" << std::endl;
        }
    };
    
    ast::expr collect_unary(ast::expr accum, const std::vector<std::string>& msgs)
    {
        for (const auto &m : msgs)
            accum = ast::message { m, { accum } };
        return accum;
    }
    
    template <class It, class Skip = boost::spirit::ascii::space_type> struct g3 : qi::grammar<It, ast::expr(), Skip> {
        g3() : g3::base_type(start) {
            using namespace boost::spirit::qi;
            namespace ph = boost::phoenix;
    
            int_       = qi::int_;
            selector_  = +qi::alnum;
    
            term_      = int_;
            unary_msg  = (term_ >> *selector_) [ _val = ph::bind(collect_unary, _1, _2) ];
            unary_term = unary_msg;
            expr_      = unary_term;
    
            start      = expr_;
        }
      private:
        template <typename Attr, typename... Args> using R = qi::rule<It, Attr(), Args...>;
    
        R<ast::expr, Skip> start, expr_, term_, unary_term, unary_msg;
        R<ast::intlit>     int_;
        R<std::string>     selector_;
    };
    
    template <class Parser, typename Result> bool test(const std::string &input, const Parser &parser, Result &result) {
        auto first = input.begin(), last = input.end();
        return qi::phrase_parse(first, last, parser, boost::spirit::ascii::space, result);
    }
    
    int main() {
        std::string const input = "42 x y";
        g3<std::string::const_iterator> p;
    
        ast::expr res;
    
        if (test(input, p, res)) {
            std::cout << "parse ok " << std::endl;
            boost::apply_visitor(ast_print(), res);
        }
    }
    

    完整列表和输出

    <强> Live On Coliru

    parse ok 
    (y (x 42)
    )
    

    打印

    [DllImport("kernel32")]
            private static extern int GetPrivateProfileString(string section,
                     string key, string def, StringBuilder retVal,
                    int size, string filePath);
     /// <summary>
            /// read value from given section and key
            /// </summary>
            /// <param name="Section">string</param>
            /// <param name="Key">string</param>
            /// <returns>string</returns>
     public string IniReadValue(string Section, string Key)
            {
                StringBuilder temp = new StringBuilder(255);
                int i = GetPrivateProfileString(Section, Key, "", temp,
                                                255, this.path);
                return temp.ToString();
    
            }