【问题标题】:boost::spirit::qiboost::spirit::qi
【发布时间】:2011-12-22 08:03:24
【问题描述】:

考虑以下代码:(Boost.Spirit 2.5.1)

qi::parse(str.begin(), str.end(), (+qi::alpha)[[](const string& s){cout << s<< '\n';}]
                                    >> (*(qi::char_(',') | qi::char_('\'')))
                                    >> qi::uint_[[](int integer){cout << integer << '\n';}]);

[[](int integer){cout &lt;&lt; integer &lt;&lt; '\n';}] 有效,但 +qi::alpha 的类似代码无效。

如何更正代码?

【问题讨论】:

  • 什么“不起作用”?你得到什么错误?还是根本不打印任何东西?
  • 我不确定是否应该发布很长的错误行。
  • @user5262:我非常肯定你必须这样做。

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


【解决方案1】:

Boost Spirit 尚不支持 C++0x/C++11 lambda1 编辑显然支持改进(我今天早些时候用旧的 bo​​ost 版本进行了测试)。现在使用 Boost 1_48 和 g++ 4.6.1,just_work 出现以下内容。耶!

qi::as_string[]

我想会想知道qi::as_string 以获得暴露的属性为 std::string 而不是默认的std::vector&lt;CharT&gt;

    qi::parse(str.begin(), str.end(),
        qi::as_string [ +qi::alpha ] 
        [
            [](const std::string&){std::cout << s << '\n';}
        ]
        >> (*(qi::char_(',') | qi::char_('\'')))
        >> qi::uint_
        [
            [](int integer){std::cout << integer << '\n';}
        ]);

但在我看来,语法不是很友好。相反,我更喜欢phoenixV2:

    qi::parse(str.begin(), str.end(),
        qi::as_string [ +qi::alpha ] [ std::cout << _1 << '\n' ]
        >> (*(qi::char_(',') | qi::char_('\'')))
        >> qi::uint_ [ std::cout << _1 << '\n' ]);

这在句法上已经短了很多,也没有那么神秘了。来看看

一个有点人为的例子展示了其中的一些实际操作,另外将属性引用直接传递到 parse 函数中:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <algorithm>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

bool reverse(std::string& value)
{
    std::reverse(value.begin(), value.end());
    return true; // false makes the parsing fail
}

int main()
{
    std::string str("sometext,123");

    auto f(str.begin()), l(str.end());

    std::string s;
    unsigned int i;

    qi::parse(f,l,
            qi::as_string [ +qi::alpha ] [ reverse ]
            >> qi::omit [ *qi::char_(",\'") ]
            >> qi::uint_,

            s, i);

    std::cout << s << std::endl;
    std::cout << i << std::endl;
}

输出:

txetemos
123

1 PhoenixV3 可能在 1_48 中对此有一些支持(尚未检查);你会想要

 #define BOOST_RESULT_OF_USE_DECLTYPE
 #define BOOST_SPIRIT_USE_PHOENIX_V3

参见例如http://boost.2283326.n4.nabble.com/Boost-Spirit-Phoenix-V3-An-Overview-td3583792.html

【讨论】:

  • Lambdas 显然工作正常,因为 OP 的 int lambda 工作。正如 Cubbi 正确指出的那样,问题在于 +qi::alpha 的综合属性是 std::vector&lt;char&gt;,而不是 std::string。从一个到另一个的转换对于非终结符是隐式完成的,而不是语义动作。
  • @ildjarn:你是对的;事情变了。已更新我的答案。我知道这种转换,我认为使用 qi::as_string 的建议也很有价值。 (FWIW 我链接到了我最初在另一条评论中了解有关额外 lambda 参数的信息的记忆线程;我现在记得要忘记这一点,至少在 gcc 上 :))跨度>
  • 我同意,qi::as_string + 一元 lambda 是一个干净的解决方案。 +1 为您的编辑。 :-]
【解决方案2】:

您的代码给了我以下编译器错误,跳过了一些位

/usr/include/boost/spirit/home/support/action_dispatch.hpp:142:13:
error: no matching function for call to
‘action_dispatch<>::do_call(
    const main()::<lambda(const string&)>&,
    action_dispatch<>::fwd_tag<std::vector<char>>,
...

归结为传递给 lambda 的参数是 vector&lt;char&gt;,而不是 string

所以,将string 替换为vector&lt;char&gt;

(+qi::alpha)[[](const std::vector<char>& s) {
      cout << std::string(s.begin(), s.end()) << '\n';
}]

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 2013-02-12
  • 1970-01-01
相关资源
最近更新 更多