Error with Phoenix _val entries in Boost.Spirit.Lex :(

I am new to Boost.Spirit.Lex. Some strange error comes up every time I try to use lex :: _ val in semantics actions in my simple lexer:

#ifndef _TOKENS_H_ #define _TOKENS_H_ #include <iostream> #include <string> #include <boost/spirit/include/lex_lexertl.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/include/phoenix_statement.hpp> #include <boost/spirit/include/phoenix_container.hpp> namespace lex = boost::spirit::lex; namespace phx = boost::phoenix; enum tokenids { ID_IDENTIFICATOR = 1, ID_CONSTANT, ID_OPERATION, ID_BRACKET, ID_WHITESPACES }; template <typename Lexer> struct mega_tokens : lex::lexer<Lexer> { mega_tokens() : identifier(L"[a-zA-Z_][a-zA-Z0-9_]*", ID_IDENTIFICATOR) , constant (L"[0-9]+(\\.[0-9]+)?", ID_CONSTANT ) , operation (L"[\\+\\-\\*/]", ID_OPERATION ) , bracket (L"[\\(\\)\\[\\]]", ID_BRACKET ) { using lex::_tokenid; using lex::_val; using phx::val; this->self = operation [ std::wcout << val(L'<') << _tokenid // << val(L':') << lex::_val << val(L'>') ] | identifier [ std::wcout << val(L'<') << _tokenid << val(L':') << _val << val(L'>') ] | constant [ std::wcout << val(L'<') << _tokenid // << val(L':') << _val << val(L'>') ] | bracket [ std::wcout << val(L'<') << _tokenid // << val(L':') << lex::_val << val(L'>') ] ; } lex::token_def<wchar_t, wchar_t> operation; lex::token_def<std::wstring, wchar_t> identifier; lex::token_def<double, wchar_t> constant; lex::token_def<wchar_t, wchar_t> bracket; }; #endif // _TOKENS_H_ 

and

 #include <cstdlib> #include <iostream> #include <locale> #include <boost/spirit/include/lex_lexertl.hpp> #include "tokens.h" int main() { setlocale(LC_ALL, "Russian"); namespace lex = boost::spirit::lex; typedef std::wstring::iterator base_iterator; typedef lex::lexertl::token < base_iterator, boost::mpl::vector<wchar_t, std::wstring, double, wchar_t>, boost::mpl::true_ > token_type; typedef lex::lexertl::actor_lexer<token_type> lexer_type; typedef mega_tokens<lexer_type>::iterator_type iterator_type; mega_tokens<lexer_type> mega_lexer; std::wstring str = L"alfa+x1*(2.836-x2[i])"; base_iterator first = str.begin(); bool r = lex::tokenize(first, str.end(), mega_lexer); if (r) { std::wcout << L"Success" << std::endl; } else { std::wstring rest(first, str.end()); std::wcerr << L"Lexical analysis failed\n" << L"stopped at: \"" << rest << L"\"\n"; } return EXIT_SUCCESS; } 

This code causes an error in the Boost header 'boost / spirit / home / lex / argument.hpp' on line 167 when compiling:

return: cannot convert 'const boost :: variant' to 'boost :: variant &'

When I do not use compilation lex :: _ val without errors.

Obviously, I am using _val incorrectly, but I do not know how to do it correctly. Please help me!:)

PS And sorry for my scary English ...

+4
source share
1 answer

I believe this is a problem in the current Phoenix related to using iostreams. As a workaround, I suggest defining a user-defined (Phoenix) function that performs the actual output:

 struct output_operation_impl { template <typename TokenId, typename Val> struct result { typedef void type; }; template <typename TokenId, typename Val> void operator()(T1 const& tokenid, T2 const& val) const { std::wcout << L'<' << tokenid << L':' << val << L'>'; } }; boost::phoenix::function<output_operation_impl> const output_operation = output_operation_impl(); 

calling it like:

 this->self = operation[ output_operation(_tokenid, _val) ] ... ; 

Regards Hartmouth

+2
source

Source: https://habr.com/ru/post/1310642/


All Articles