提升精神v2编译错误 - 尝试使用符号稍微更难一点,并在某处遗漏重要的一点

时间:2010-08-05 06:38:31

标签: c++ boost boost-spirit

我尝试了各种方法来解决这个问题,使用地图和强制转换,将解析分成不同的子部分,直接使用std :: vector并尝试_r1等,但我似乎未能掌握使用的基本内容属性。

我想解析一行,例如:

DEFMACRO macroname param1 param2 param3 ... paramN

并将macroname与其params列表一起添加到qi :: symbols解析器中。

匹配

lit("DEFMACRO") >> (+char_) >> predicate_

并且放入defmacro结构工作正常,但是当我尝试使用结果或将其整体存储为符号解析器的数据元素时,我得到了表单的错误

无法从'const boost :: phoenix :: actor'转换为'const client :: defmacro'

  • 但无论我尝试什么,我总是无法“从'const boost :: phoenix :: actor'转换为”我试图使用的任何数据类型(例如直接到std :: vector或结构中的其他变体。也试过语法上的变化,但到目前为止都是空白。

下面是代码片段,然后是针对我的问题的这个变体的编译器输出。

我对未能掌握一些重要概念的任何解释都非常欢迎。

将VC ++ 2008与Spirit 1.42一起使用。

由于 瑞克

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_int.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <string>
#include <vector>

namespace client
{
    namespace fusion = boost::fusion;
    namespace phoenix = boost::phoenix;
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

 typedef std::vector<std::string> predicate;

 struct defmacro
    {
  std::string name;  // identifier for macro
  predicate params;  // parameters for macro
    };

}

BOOST_FUSION_ADAPT_STRUCT(
    client::defmacro,
    (std::string, name)
 (client::predicate, params)
)

namespace client
{
    template <typename Iterator>
    struct awe_grammar
      : qi::grammar<Iterator, awe(), qi::locals<std::string>, ascii::space_type>
    {
        awe_grammar()
          : awe_grammar::base_type(x, "x")
        {
            using qi::lit;
            using qi::eol;
            using qi::int_;
            using ascii::char_;
            using namespace qi::labels;

            using phoenix::at_c;

   long line_no=1;
   qi::symbols<std::string,  defmacro> macros;

   eol_ = eol[ref(line_no)++];

   predicate_ %= *(+char_); 

   defmacro_line_ %= (lit("DEFMACRO") >> (+char_) >> predicate_ >> eol_);

   // ******** This line will not compile *************************
   defmacro_  = defmacro_line_[macros.add(at_c<0>(_1),_1)];
   // *************************************************************
        }

  qi::rule<Iterator, defmacro(), ascii::space_type> defmacro_line_;
  qi::rule<Iterator, void(), ascii::space_type> defmacro_;
        qi::rule<Iterator, predicate(), ascii::space_type> predicate_;

 };
}

2>v:\awe\parser\parser\spirit\spirit_eg.cpp(XXX) : error C2664: 'const boost::spirit::qi::symbols<Char,T>::adder &boost::spirit::qi::symbols<Char,T>::adder::operator ()<boost::phoenix::actor<Eval>>(const Str &,const T &) const' : cannot convert parameter 2 from 'const boost::phoenix::actor<Eval>' to 'const client::defmacro &'
2>        with
2>        [
2>            Char=std::string,
2>            T=client::defmacro,
2>            Eval=boost::phoenix::composite<boost::phoenix::at_eval<0>,boost::fusion::vector<boost::spirit::argument<0>,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>>,
2>            Str=boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::at_eval<0>,boost::fusion::vector<boost::spirit::argument<0>,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>>>
2>        ]
2>        and
2>        [
2>            Eval=boost::spirit::argument<0>
2>        ]
2>        Reason: cannot convert from 'const boost::phoenix::actor<Eval>' to 'const client::defmacro'
2>        with
2>        [
2>            Eval=boost::spirit::argument<0>
2>        ]
2>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
2>        v:\awe\parser\parser\spirit\spirit_eg.cpp(351) : while compiling class template member function 'client::awe_grammar<Iterator>::awe_grammar(void)'
2>        with
2>        [
2>            Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>
2>        ]
2>        v:\awe\parser\parser\spirit\spirit_eg.cpp(622) : see reference to class template instantiation 'client::awe_grammar<Iterator>' being compiled
2>        with
2>        [
2>            Iterator=std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char>>
2>        ]

2 个答案:

答案 0 :(得分:1)

您可以在语法之外的符号中添加值,如下所示:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_int.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <string>
#include <vector>

namespace client
{
    namespace fusion = boost::fusion;
    namespace phoenix = boost::phoenix;
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    typedef std::vector<std::string> predicate;

    struct defmacro
    {
        std::string name;  // identifier for macro
        predicate params;  // parameters for macro
    };

    typedef std::vector<defmacro> awe;
}

BOOST_FUSION_ADAPT_STRUCT(
    client::defmacro,
    (std::string, name)
    (client::predicate, params)
)

namespace client
{
    template <typename Iterator>
    struct awe_grammar
        : qi::grammar<Iterator, awe()>
    {
        awe_grammar()
            : awe_grammar::base_type(start_)
        {
            using qi::lit;
            using qi::eol;
            using ascii::char_;
            using ascii::blank;
            using ascii::space;
            using namespace qi::labels;
            using phoenix::ref;
            using phoenix::at_c;

            line_no = 0;

            eol_ = eol[++ref(line_no)];

            identifier_ %= qi::lexeme[+(char_ - space)];

            predicate_ %= (identifier_ % blank) >> eol_;

            defmacro_line_ %=
                   lit("DEFMACRO ")
                >> identifier_ >> ' '
                >> predicate_
            ;

            start_ %= +defmacro_line_;
        }

        long line_no;

        qi::rule<Iterator, void()       > eol_;
        qi::rule<Iterator, defmacro()   > defmacro_line_;
        qi::rule<Iterator, awe()        > start_;
        qi::rule<Iterator, std::string()> identifier_;
        qi::rule<Iterator, predicate()  > predicate_;

    };
}

#include <cstdlib>
#include <iostream>
#include "awe_grammar.h"

template <typename P, typename T>
void test_parser_attr(
                      char const* input, P const& p, T& attr, bool full_match = true)
{
    using boost::spirit::qi::parse;

    char const* f(input);
    char const* l(f + strlen(f));
    if (parse(f, l, p, attr) && (!full_match || (f == l)))
        std::cout << "ok" << std::endl;
    else
        std::cout << "fail" << std::endl;
}

int main( /*int _argc, char * _argv[]*/ )
{
    typedef client::awe_grammar<char const *> my_grammar;
    my_grammar g;
    client::awe result;

    test_parser_attr(
        "DEFMACRO macroname param1 param2 param3\n"
        "DEFMACRO macro2 param1 param2\n",
        g,
        result,
        true
    );

    ////////////////////
    // adding
    ////////////////////
    boost::spirit::qi::symbols<char, client::defmacro> macros;
    for (size_t i = 0; i < result.size(); i++)
    {
        macros.add(result[i].name, result[i]);
    }

    return EXIT_SUCCESS;
}

之后,您可以使用macros所需的内容(例如,将其传递给另一种语法)。

答案 1 :(得分:0)

试试这个:

// ******** This line will not compile *************************
using qi::_val;
defmacro_  = defmacro_line_[macros.add(at_c<0>(_val),_1)];
// *************************************************************