ошибка компиляции boost spirit v2 - попытка использовать символы для чего-то более сложного и где-то упустить важный момент - PullRequest
1 голос
/ 05 августа 2010

Я пробовал разные подходы к решению этой проблемы с помощью карт и приведения, разбивая анализ на разные части, используя непосредственный std :: vector и пробуя _r1 и т. Д., Но мне, кажется, не удалось понять что-то фундаментальное в использованииатрибутов.

Я хочу проанализировать строку, такую ​​как:

DEFMACRO macroname param1 param2 param3 ... paramN

и добавить имя макронамера в анализатор qi :: symbols вместе со списком параметров.

Совпадение с

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

и помещение в структуру defmacro работает нормально, но когда я пытаюсь использовать результат или сохранить его целиком как элемент данных синтаксического анализатора символов, я получаю ошибки вида

не может преобразовать из 'const boost :: phoenix :: actor' в 'const client :: defmacro'

  • , но что бы я ни пытался, мне всегда не удается "преобразовать из" const boost :: phoenix:: actor 'to "любой тип данных, который я пытаюсь использовать (например, прямо в std :: vector или другие вариации структур. Также пробовал вариации синтаксиса, но до сих пор рисовал пробел.

Фрагмент коданиже, foОбращает на себя внимание вывод компилятора для этого варианта моей проблемы.

Любое объяснение моей неспособности понять какую-то важную концепцию очень приветствуется.

Использование 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 ]

1 голос
/ 05 августа 2010

Вы можете добавлять значения к символам за пределами вашей грамматики следующим образом:

#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 то, что вы хотите (например, передать его в другую грамматику).

0 голосов
/ 06 января 2011

Попробуйте это:

// ******** This line will not compile *************************
using qi::_val;
defmacro_  = defmacro_line_[macros.add(at_c<0>(_val),_1)];
// *************************************************************
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...