1

我已经根据Spirit lex 示例 4中显示的代码编写了一个工作令牌解析器

我的一条规则看起来像这样

    set_name 
        =   (   tok.set_ >> tok.name_ >> tok.identifier )
            [
                std::cout << val("set name statement to: ") << _3 << "\n"
            ]
        ;

这很好用。当出现

SET NAME xyz

它按我的预期输出

将名称语句设置为:xyz

现在我想做一些有用的事情,将找到的名称存储到一个类中。从解析器语义示例工作,我编写了这段代码

  class writer
    {
    public:
        void print(string const& s) const
        {
            std::cout << s << std::endl;
        }
    };

  writer w;

  ...

    set_name 
        =   (   tok.set_ >> tok.name_ >> tok.identifier )
            [
                boost::bind( &writer::print, &w, ::_3 )
            ]
        ;

这不编译

1>C:\Program Files\boost\boost_1_44\boost/bind/bind.hpp(318) : 错误 C2664: 'R boost::_mfi::cmf1::operator ()(const U &,A1) const' :无法将参数 2 从 'bool' 转换为 'const std::basic_string'
1> 与
1> [
1> R=空,
1> T=eCrew::rule::writer,
1> A1=const std::string &,
1> U=eCrew::rule::writer *
1>]
1> 和
1> [
1> _Elem=字符,
1> _Traits=std::char_traits,
1> _Ax=std::分配器
1>]
1> 原因:无法从 'bool' 转换为 'const std::string'
1> 没有构造函数可以采用源类型,或者构造函数重载决议不明确

为什么编译器抱怨试图从 bool 转换为 string?我看不到布尔值。

4

1 回答 1

3

占位符在

std::cout << val("set name statement to: ") << _3 << "\n"

指的是boost::spirit::_3,这是一个 boost.phoenix v2 占位符。占位符在

boost::bind(&writer::print, &w, ::_3)

是 boost.bind 占位符(自然)。

这些占位符共享相同的行为,甚至引用相同的数据。_N形式的 Phoenix 占位符指的是解析器的第 N 个子属性,而绑定占位符有不同的含义:

  • _1 指的是整个解析器的属性
  • _2 指解析器的上下文
  • _3 指的是bool&“命中”参数

在您的情况下,最简单的解决方案是使用boost::phoenix::bind而不是boost::bind,这样您就可以继续使用_3来引用解析器的第三个子属性,而不必在writer::print.

或者,只附加语义操作,tok.identifier以便 boost.bind 的::_1工作如您所愿:

set_name
  = tok.set_
    >> tok.name_
    >> tok.identifier[boost::bind(&writer::print, &w, ::_1)]
;
于 2011-03-29T21:14:54.187 回答