c++ - Boost.Spirit.Lex :( 中 Phoenix 占位符 _val 出错

标签 c++ boost boost-spirit

我是 Boost.Spirit.Lex 的新手。 每次我尝试在我的简单词法分析器的语义操作中使用 lex::_val 时,都会出现一些奇怪的错误:

#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_

#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;
}

此代码在编译时导致第 167 行的 Boost header “boost/spirit/home/lex/argument.hpp”中出现错误:

return: can't convert 'const boost::variant' to 'boost::variant &'

当我不使用 lex::_val 时程序编译没有错误。

显然,我以错误的方式使用了 _val,但我不知道如何正确地使用它。请帮助! :)

附言对不起我糟糕的英语……

最佳答案

我相信这是当前 Phoenix 中与使用 iostream 相关的问题。作为解决方法,我建议定义一个自定义(Phoenix)函数来执行实际输出:

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();

称其为:

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

问候哈特穆特

关于c++ - Boost.Spirit.Lex :( 中 Phoenix 占位符 _val 出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2890635/

相关文章:

c++ - 为什么一个类需要移动操作来绑定(bind)到一个 std::function ,该函数具有该类按值传递的签名?

c++ - Qt在主线程中获取线程ID?

c++ - 不使用 boost 绑定(bind)

c++ - 使用 boost::spirit 解析引用字符串

c++ - Boost Spirit 不检查 int 溢出

c++ - 在 boost spirit 语义 Action 中通过 std::map 过滤合成属性

C++ 如何在 C++ 中使用 dlopen()?

c++ - 具有动态列数的 QML TableView

c++ - 找不到以下 Boost 库 : boost_system

android - iOS 和 Android 都支持 Boost C++ 线程吗?