Boost spirit:使成员函数中的解析器无效
Boost spirit: Invalidate parser from member function
这篇文章(boost spirit语义动作参数)解释了如何使用签名
使来自普通函数的匹配无效void f(int attribute, const boost::fusion::unused_type& it, bool& mFlag)
我想使语法的成员函数的匹配无效:
#include <boost/spirit/home/qi.hpp>
#include <boost/spirit/home/phoenix.hpp>
#include <iostream>
#include <string>
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
class moduleAccessManager
{
public:
bool getModule(const std::string name)
{
if(name == "cat" || name == "dog")
return true;
else
return false;
}
};
void globalIsModule(std::string moduleName, const boost::spirit::unused_type&, bool& mFlag)
{
moduleAccessManager acm; /* Dirty workaround for this example */
if(acm.getModule(moduleName))
std::cout << "[isModule] Info: Found module with name >" << moduleName << "<" << std::endl;
else
{
std::cout << "[isModule] Error: No module with name >" << moduleName << "<" << std::endl;
mFlag = false; // No valid module name
}
}
template <typename Iterator, typename Skipper>
class moduleCommandParser : public qi::grammar<Iterator, Skipper>
{
private:
moduleAccessManager* m_acm;
qi::rule<Iterator, Skipper> start, module;
public:
std::string m_moduleName;
moduleCommandParser(moduleAccessManager* acm)
: moduleCommandParser::base_type(start)
, m_acm(acm)
, m_moduleName("<empty>")
{
module = qi::as_string[qi::lexeme[+(~qi::char_(' '))]]
[&globalIsModule] // This works fine
// [phoenix::bind(&moduleCommandParser::isModule, this)] // Compile error
;
start = module >> qi::as_string[+(~qi::char_('n'))];
};
void isModule(std::string moduleName, const boost::spirit::unused_type&, bool& mFlag)
{
// Check if a module with moduleName exists
if(m_acm->getModule(moduleName))
std::cout << "[isModule] Info: Found module with name >" << moduleName << "<" << std::endl;
else
{
std::cout << "[isModule] Error: No module with name >" << moduleName << "<" << std::endl;
mFlag = false; // No valid module name
}
};
};
int main()
{
moduleAccessManager acm;
moduleCommandParser<std::string::const_iterator, qi::space_type> commandGrammar(&acm);
std::string str;
std::string::const_iterator first;
std::string::const_iterator last;
str = "cat run";
first = str.begin();
last = str.end();
qi::phrase_parse(first, last, commandGrammar, qi::space);
str = "bird fly";
first = str.begin();
last = str.end();
qi::phrase_parse(first, last, commandGrammar, qi::space);
}
Coliru上的代码:http://coliru.stacked-crooked.com/a/4319b38a6d36c362
重要的部分是这两行:
[&globalIsModule] // This works fine
// [phoenix::bind(&moduleCommandParser::isModule, this)] // Compile error
使用全局函数工作得很好,但这不是我的选择,因为我需要访问特定于解析器的m_acm对象。
如何将成员函数绑定到语义操作,同时能够使该成员函数的匹配无效(使用上面提到的3个参数函数签名)?
有两种方法:
- 你可以使用Phoenix actors分配给
qi::_val
- 您可以在"原始"语义动作函数中分配第三个参数(
bool&
)
示例如下:
- 限制现有的Boost。Spirit real_parser(带策略)(使用
_val
)
解析语义动作函数(带第三个参数):
- boost spirit语义动作参数
在您的情况下,您有一个成员函数,大致具有"原始语义操作函数"签名。当然,您必须绑定this
参数(因为它是一个非静态成员函数)。
请注意,在这种特殊情况下,phoenix::bind
不是正确的绑定,因为Phoenix Actors将被认为是"熟"(而不是原始的)语义动作,并且它们将在Spirit上下文中执行。
你可以选择
-
使用
boost::bind
(甚至std::bind
)绑定到保持成员函数(!)的性的函数:
这个作品[boost::bind(&moduleCommandParser::isModule, this, ::_1, ::_2, ::_3)]
: 生活在Coliru
-
使用"cooked"语义动作,直接分配给
_pass
上下文占位符:
Live On Coliru[qi::_pass = phoenix::bind(&moduleAccessManager::getModule, m_acm, qi::_1)]
后一个例子,供将来参考:
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <string>
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
class moduleAccessManager {
public:
bool getModule(const std::string name) {
return name == "cat" || name == "dog";
}
};
void globalIsModule(std::string moduleName, const boost::spirit::unused_type&, bool& mFlag)
{
moduleAccessManager acm; /* Dirty workaround for this example */
if(acm.getModule(moduleName))
std::cout << "[isModule] Info: Found module with name >" << moduleName << "<" << std::endl;
else
{
std::cout << "[isModule] Error: No module with name >" << moduleName << "<" << std::endl;
mFlag = false; // No valid module name
}
}
template <typename Iterator, typename Skipper>
class moduleCommandParser : public qi::grammar<Iterator, Skipper>
{
private:
moduleAccessManager* m_acm;
qi::rule<Iterator, Skipper> start, module;
public:
std::string m_moduleName;
moduleCommandParser(moduleAccessManager* acm)
: moduleCommandParser::base_type(start)
, m_acm(acm)
, m_moduleName("<empty>")
{
using namespace phoenix::arg_names;
module = qi::as_string[qi::lexeme[+(~qi::char_(' '))]]
[qi::_pass = phoenix::bind(&moduleAccessManager::getModule, m_acm, qi::_1)]
;
start = module >> qi::as_string[+(~qi::char_('n'))];
};
};
int main()
{
moduleAccessManager acm;
moduleCommandParser<std::string::const_iterator, qi::space_type> commandGrammar(&acm);
std::string str;
std::string::const_iterator first;
std::string::const_iterator last;
str = "cat run";
first = str.begin();
last = str.end();
std::cout << str << std::boolalpha
<< qi::phrase_parse(first, last, commandGrammar, qi::space)
<< "n";
str = "bird fly";
first = str.begin();
last = str.end();
std::cout << str << std::boolalpha
<< qi::phrase_parse(first, last, commandGrammar, qi::space)
<< "n";
}
相关文章:
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 程序中的布尔函数返回输入的范围无论如何都是无效的
- 在这个函数中是有缺陷的,因为取消引用 null 是无效的,所以我想更改代码
- 在 Microsoft Access SQL 中调用自定义 DLL 函数时传递的内存地址无效
- C++无效的函数类型转换
- C++无效使用非静态成员函数?
- 模板和无效函数调用C++
- 控件到达非无效函数的末尾[-Wreturn类型]
- 获取控制权到达非无效函数警告的末尾,尽管我在 th 函数中有返回语句
- C++ 指针无效函数问题
- 为什么我总是得到 - 警告:控制达到非无效函数的末尾 [-Wreturn-type]
- 在无效函数中使用退出来纠正错误是否是一种好的做法
- 在C++ 通过按键进入和退出无效函数调用
- 指向指向无效函数参数的指针
- Xcode - 控制到达非无效函数运算符错误的末尾
- C++:对无效函数的未定义引用
- 二叉树无效函数
- 控件到达非无效函数的末尾
- 控件到达非无效函数的末尾
- 控制可能会到达非无效函数 xcode 的末尾