【问题标题】:cannot compile boost-spirit example for changing token value using Phoenix actor无法编译使用 Phoenix actor 更改令牌值的 boost-spirit 示例
【发布时间】:2013-05-13 14:58:06
【问题描述】:

当我尝试编译下面的代码时(使用来自 boost\spirit\home\lex\argument.hpp: value_setter 的示例),我收到以下编译器错误:

c:\program files (x86)\boost\boost_1_50\boost\range\iterator.hpp(63) : error C2039: 'type' : is not a member of 'boost::mpl::eval_if_c<C,F1,F2>'
with
[
    C=true,
    F1=boost::range_const_iterator<const char *>,
    F2=boost::range_mutable_iterator<const char *const >
]
c:\program files (x86)\boost\boost_1_50\boost\range\iterator_range_core.hpp(56) : see reference to class template instantiation 'boost::range_iterator<C>' being compiled
with
[
    C=const char *const 
]
...

没有语义操作,一切都编译得很好。示例如下:

#include <boost/spirit/include/lex_lexertl.hpp>
namespace lex = boost::spirit::lex;

template <typename Lexer>
struct my_tokens : lex::lexer<Lexer>
{
    my_tokens()
    {
        identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
        this->self = identifier  [ lex::_val = "identifier" ] // problematic action
                   ;
    }
    lex::token_def<> identifier;
};

int main()
{
    typedef std::string::iterator base_iterator_type;
    typedef
        lex::lexertl::actor_lexer<lex::lexertl::token<base_iterator_type> > 
        lexer_type;

    my_tokens<lexer_type> myLexer;
    std::string str = "id1";
    base_iterator_type first = str.begin();
    bool r = lex::tokenize(first, str.end(), myLexer);

    if (!r) {
        std::string rest(first, str.end());
        std::cerr << "Lexical analysis failed\n" << "stopped at: \"" 
                  << rest << "\"\n";
    }
}

出了什么问题?如何设置/更改令牌的值?

【问题讨论】:

    标签: c++ boost-spirit boost-spirit-lex


    【解决方案1】:

    您的 token_def 应该公开预期的属性类型(编译错误表明您正在将字符串文字分配给 iterator_range):

    lex::token_def<std::string> identifier;
    

    现在,匹配作业中的类型

    this->self = identifier  [ lex::_val = std::string("identifier") ]
    

    不要忘记更新令牌类型以反映可能的令牌属性类型集:

    typedef
        lex::lexertl::actor_lexer<lex::lexertl::token<base_iterator_type,
            boost::mpl::vector<std::string> > > 
        lexer_type;
    

    现在应该可以编译了:

    #include <boost/spirit/include/lex_lexertl.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    namespace lex = boost::spirit::lex;
    namespace phx = boost::phoenix;
    
    template <typename Lexer>
    struct my_tokens : lex::lexer<Lexer>
    {
        my_tokens()
        {
            identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
            this->self = identifier  [ lex::_val = std::string("identifier") ]
                       ;
        }
        lex::token_def<std::string> identifier;
    };
    
    int main()
    {
        typedef std::string::iterator base_iterator_type;
        typedef
            lex::lexertl::actor_lexer<lex::lexertl::token<base_iterator_type, boost::mpl::vector<std::string> > > 
            lexer_type;
    
        my_tokens<lexer_type> myLexer;
        std::string str = "id1";
        base_iterator_type first = str.begin();
        bool r = lex::tokenize(first, str.end(), myLexer);
    
        if (!r) {
            std::string rest(first, str.end());
            std::cerr << "Lexical analysis failed\n" << "stopped at: \"" 
                      << rest << "\"\n";
        }
    }
    

    【讨论】:

    • 将属性类型添加到令牌类型定义的可能性很棘手。关于这个主题的文档很短。这是我遗漏的关键点。谢谢指出!
    • 是否有可能基于令牌正则表达式中的匹配组形成令牌值?或者至少可以访问它们?
    • 我为此提出了一个单独的问题:stackoverflow.com/questions/35476454/…
    猜你喜欢
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    相关资源
    最近更新 更多