2015-12-07 7 views
1

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

boost\spirit\home\qi\detail\assign_to.hpp(164): error C2440: 'static_cast' : cannot convert from 'const wchar_t' to 'element_type'

Комментарий прямо над линией 164 гласит:

// This handles the case where the attribute is a single element fusion 
// sequence. We silently assign to the only element and treat it as the 
// attribute to parse the results into. 

Я прочитал сообщение «Spirit Qi attribute propagation issue with single-member struct» и, следовательно, добавил qi::eps ко всем правилам. Тем не менее, это не делает трюк, поэтому я также опробовал обходные пути № 1 и № 3 выше, но безрезультатно. Поэтому я не уверен, что ошибка связана с последовательностью слияния одного элемента на всех ...

Как решить эту проблему?

-Mario

#pragma once 

#include <string> 
#include <vector> 

#define BOOST_SPIRIT_UNICODE 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/qi_alternative.hpp> 

namespace nsunic = boost::spirit::unicode; 
namespace nsqi = boost::spirit::qi; 


namespace overmath 
{ 
    struct identifier 
    { 
     std::wstring name; 
    }; 

    struct assignment 
    { 
     identifier variable_reference; 
     identifier expression; 
    }; 

    struct statement 
    { 
     assignment assign; 
    }; 

    struct statement_list 
    { 
     std::vector<statement> statements; 
    }; 

    struct function 
    { 
     identifier name; 
     statement_list slist; 
    }; 

    struct program 
    { 
     std::vector<function> functions; 
    }; 

} 

BOOST_FUSION_ADAPT_STRUCT(
    overmath::identifier, 
    (std::wstring, name) 
) 

BOOST_FUSION_ADAPT_STRUCT(
    overmath::assignment, 
    (overmath::identifier, variable_reference) 
    (overmath::identifier, expression) 
) 

BOOST_FUSION_ADAPT_STRUCT(
    overmath::statement, 
    (overmath::assignment, assign) 
) 

BOOST_FUSION_ADAPT_STRUCT(
    overmath::statement_list, 
    (std::vector<overmath::statement>, statements) 
) 

BOOST_FUSION_ADAPT_STRUCT(
    overmath::function, 
    (overmath::identifier, name) 
    (overmath::statement_list, slist) 
) 

BOOST_FUSION_ADAPT_STRUCT(
    overmath::program, 
    (std::vector<overmath::function>, functions) 
) 


namespace overmath 
{ 



    template<typename Iterator> struct function_parser : nsqi::grammar<Iterator, program(), nsqi::space_type> 
    { 
     function_parser() : function_parser::base_type(program) 
     { 
      identifier %= 
       nsqi::eps 
       >> +nsqi::alnum; 

      assignment %= 
       nsqi::eps 
       >> identifier 
       >> nsqi::char_('=') 
       >> identifier; 

      statement %= 
       nsqi::eps 
       >> assignment; 

      statement_list %= 
       nsqi::eps 
       >> +statement; 

      function %= 
       nsqi::eps 
       >> nsqi::lit("def") 
       >> identifier 
       >> nsqi::char_('(') 
       >> nsqi::char_(')') 
       >> statement_list 
       >> nsqi::lit("enddef"); 

      program %= 
       nsqi::eps 
       >> +function; 
     } 

     nsqi::rule<Iterator, identifier()> identifier; 
     nsqi::rule<Iterator, assignment(), nsqi::space_type> assignment; 
     nsqi::rule<Iterator, statement(), nsqi::space_type> statement; 
     nsqi::rule<Iterator, statement_list(), nsqi::space_type> statement_list; 
     nsqi::rule<Iterator, function(), nsqi::space_type> function; 
     nsqi::rule<Iterator, program(), nsqi::space_type> program; 
    }; 


    template<typename Iterator> std::wstring parse(Iterator first, Iterator last) 
    { 
     using nsqi::phrase_parse; 

     program f; 
     function_parser<Iterator> fp; 

     auto b = phrase_parse(first, last, fp, nsqi::space, f); 
     if(b) 
     { 
      return std::wstring(L"OK"); 
     } 
     return std::wstring(L"FAIL"); 
    } 

} 
+0

Я думаю, проблема в правиле 'assign', у вас есть' nsqi :: char _ ('=') ', который предоставляет атрибут, когда вы должны иметь' nsqi :: lit ('=') '(' lit (L '=') '?). И вы определенно перешли за борт с 'eps', вам нужны только они, когда у вас есть один элемент, и этот элемент является «контейнером», поэтому «идентификатор», «оператор-лист» и «программа». – llonesmiz

+0

http://coliru.stacked-crooked.com/a/dde9543607c06127 – llonesmiz

+0

Как я могу сделать этот комментарий моим принятым ответом? – Sakuragaoka

ответ

0

Некоторые из ваших правил имеют обычную проблему, связанную с чем-то контейнер, как в качестве единственного элемента в адаптированной структуры, что объясняется в этом вопросе вы связаны, но вы обошли его добавив qi :: eps (даже если это не было действительно необходимо).

Ошибка, связанная с вашим кодом, обусловлена ​​правилом assignment. Он имеет атрибут overmath::assignment который в основном your_attr=tuple<identifier,identifier>. Если мы проанализируем его синтезированный атрибут, мы увидим, что это synt_attr=tuple<identifier,wchar_t,identifier>. Когда Spirit анализирует ваше правило, он пытается присвоить синтезированный атрибут вашему атрибуту. Он присваивает первый элемент synt_attr вашему_attr (идентификатор к идентификатору, без проблем), затем он пытается назначить второй элемент (wchar_t для идентификатора), но он не работает. Поскольку идентификатор представляет собой адаптированную структуру (в основном последовательность слияния tuple<wstring>), она превращает wchar_t в одну последовательность элементов tuple<wchar_t> и пытается назначить ее (wchar_t на wstring и не удается), вызывая ошибку.

Так что проблема в том, что у вас есть дополнительный wchar_t, которого не должно быть. Это связано с использованием вами char_('='), если вы используете lit('=') (или даже omit[char_('=')]), он должен работать.