gpt4 book ai didi

c++ - 使用 Spirit 的语义 Action 顺序(引用 Phoenix)

转载 作者:行者123 更新时间:2023-11-30 05:40:50 28 4
gpt4 key购买 nike

我正在构建一个解析器来执行用户可能在命令行中输入的命令。命令的第一部分是它所属的模块,第二部分是要调用的模块的函数。

附加到第一个解析器的是语义操作(使用 boost::phoenix::ref()),它应该将模块名称存储在变量 m_moduleName 中。附加到第二个解析器的是另一个语义操作,它使用前一个变量作为参数调用函数 printParameters。

#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/home/qi.hpp>
#include <boost/bind.hpp>

#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;


void printParameters(const std::string & module, const std::string & command)
{
std::cout << "Module name during parse: " << module << std::endl;
std::cout << "Command name during parse: " << command << std::endl;
}


template <typename Iterator>
struct myCommandParser : public qi::grammar<Iterator>
{
myCommandParser() : myCommandParser::base_type(start)
{
start = qi::as_string[+(~qi::char_(' '))][phoenix::ref(m_moduleName) = qi::_1]
>> qi::as_string[+(~qi::char_('\n'))][boost::bind(&printParameters, m_moduleName, ::_1)];
};

qi::rule<Iterator> start;
std::string m_moduleName;
};


int main()
{
myCommandParser<std::string::const_iterator> commandGrammar;

commandGrammar.m_moduleName = std::string("initial_default");
std::cout << "Module name before parsing: " << commandGrammar.m_moduleName << std::endl;

std::string str("mod01 cmd02\n");
std::string::const_iterator first = str.begin();
std::string::const_iterator last = str.end();
qi::parse(first, last, commandGrammar);

std::cout << "Module name after parsing: " << commandGrammar.m_moduleName << std::endl;
}

预期结果:在第一个语义操作期间,m_moduleName 的值应设置为 mod01,它应在 printParameters 函数期间打印。

实际结果(程序输出):

Module name before parsing: initial_default
Module name during parse:
Command name during parse: cmd02
Module name after parsing: mod01

在构建这个最小示例时,我注意到在执行解析函数期间 m_moduleName 的值为,尽管它已事先设置为“initial_default”。

有人可以解释一下这里到底发生了什么吗?

为什么值为空而不是 mod01

最佳答案

您不能混合使用 Boost Bind/Phoenix/Lambda/Qi/std 占位符。

事实上,您不能在语义操作中使用 Boost Bind。

您想将 phoenix::bindqi::_1 一起使用。哦,在 m_moduleName 周围添加 phoenix::cref()

除此之外,您根本不想在这种情况下使用丑陋的语义操作:

简化:

Live On Coliru

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

int main()
{
std::string const str("mod01 cmd02\n");
std::string moduleName, command;
qi::parse(str.begin(), str.end(), +~qi::char_(' ') >> +~qi::char_('\n'), moduleName, command);

std::cout << "Module name after parsing: " << moduleName << "\n";
std::cout << "Command after parsing: " << command << "\n";
}

打印

Module name after parsing: mod01
Command after parsing: cmd02

参见 BOOST_FUSION_ADAPT_STRUCT 和 boost/fusion/adapted/std_pair.hpp 例如扩展/自动化的方法

关于c++ - 使用 Spirit 的语义 Action 顺序(引用 Phoenix),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31407742/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com