在语义动作中添加到气符表中
Add to a spirit qi symbol table in a semantic action
根据boost::spirit::qi::symbols文档的开头一段,我认为从语义操作向qi::符号添加符号不会太难。不幸的是,这似乎并不像我想象的那么简单。
以下测试代码显示了问题:
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
namespace qi = boost::spirit::qi;
typedef qi::symbols<char, unsigned int> constants_dictionary;
template <typename Iter> struct parser : public qi::grammar<Iter, qi::space_type> {
parser(constants_dictionary &dict) : parser::base_type(start) {
start = qi::lit("@") >> ((+qi::char_) >> qi::uint_)[dict.add(qi::_1, qi::_2)];
}
qi::rule<Iter> start;
};
int main() {
constants_dictionary dict;
parser<std::string::const_iterator> prsr(dict);
std::string test = "@foo 3";
parse(test.begin(), test.end(), prsr, qi::space);
}
给出与VS2010:中的qi::_2相关的类型错误
C:UserskCodingdashCompilerspirit_test.cpp(12) : error C2664: 'const boost::
spirit::qi::symbols<Char,T>::adder &boost::spirit::qi::symbols<Char,T>::adder::o
perator ()<boost::spirit::_1_type>(const Str &,const T &) const' : cannot conver
t parameter 2 from 'const boost::spirit::_2_type' to 'const unsigned int &'
with
[
Char=char,
T=unsigned int,
Str=boost::spirit::_1_type
]
Reason: cannot convert from 'const boost::spirit::_2_type' to 'const uns
igned int'
No user-defined-conversion operator available that can perform this conv
ersion, or the operator cannot be called
C:UserskCodingdashCompilerspirit_test.cpp(10) : while compiling cla
ss template member function 'parser<Iter>::parser(constants_dictionary &)'
with
[
Iter=std::_String_const_iterator<char,std::char_traits<char>,std::al
locator<char>>
]
C:UserskCodingdashCompilerspirit_test.cpp(21) : see reference to cl
ass template instantiation 'parser<Iter>' being compiled
with
[
Iter=std::_String_const_iterator<char,std::char_traits<char>,std::al
locator<char>>
]
(为讨厌的VS2010错误风格道歉)
我应该使用什么语法来从此表中添加(以及稍后删除)符号?
这个问题以前已经回答过了。然而,你发布的代码有很多问题,所以我会逐一修复,以免你不必要地盯着错误消息页面看。
工作代码(加上输出验证)位于liveworkspace.org上。
注:
-
语义操作必须是Phoenix参与者,即您需要
boost::bind
、phoenix::bind
、std::bind
phoenix::lambda<>
或phoenix::function<>
-
函数指针或多态可调用对象(根据文档)
我推荐
phoenix::bind
(在这种特殊情况下),它显示在下面
- 解析程序的队长和启动规则不匹配
qi::char_
吃掉所有字符。再加上船长在解析失败时,因为(显然)值中的数字也是被CCD_ 8吃掉。我向您展示了基于qi::lexeme[+qi::graph]
的众多解决方案之一- 使用
qi::lexeme
"绕过"队长(即防止+qi::graph进行切割跨越空白,因为队长跳过了它) qi::parse
不需要船长;使用qi::phrase_parse
它出现工作的原因是任何尾随的"variadic"参数绑定到解析器的公开属性,在本例中为因此为qi::unused_type
)- 如果要将
test.begin()
和test.end()
直接传递到qi::phrase_parse
,您需要明确您想要const迭代器。这个更典型的解决方案是引入显式类型的变量(例如first
和last
)
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef qi::symbols<char, unsigned int> constants_dictionary;
template <typename Iter> struct parser : qi::grammar<Iter, qi::space_type>
{
parser(constants_dictionary &dict) : parser::base_type(start)
{
start = qi::lit("@") >> (qi::lexeme [+qi::graph] >> qi::uint_)
[ phx::bind(dict.add, qi::_1, qi::_2) ]
;
}
qi::rule<Iter, qi::space_type> start;
};
int main() {
constants_dictionary dict;
parser<std::string::const_iterator> prsr(dict);
const std::string test = "@foo 3";
if (qi::phrase_parse(test.begin(), test.end(), prsr, qi::space))
{
std::cout << "check: " << dict.at("foo") << "n";
}
}
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 如何在C++中从两个单独的for循环中添加两个数组
- 何时在引用或唯一指针上使用移动语义
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 如何仅为一个函数添加延迟
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 如何将更多文件夹添加到c++include路径
- 如何将元素添加到数组的线程安全函数?
- QT通过C++添加映射QML项目
- 如何从具有移动语义的类对象中生成共享指针
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- Boost Spirit,获取迭代器内部语义动作
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 向包含POD和非POD成员的现有结构添加移动语义
- 在语义动作中添加到气符表中
- 首先创建字符串,然后通过移动语义将其添加到 vector 或在 vector 中创建元素是否具有内存效率
- 在boost::spirit::lex中,如何添加带有语义动作和令牌ID的令牌