英文:
Why does this nabialek trick not work in my simple grammar with boost::spirit::qi
问题
我想使用boost::spirit解析命令行参数。与其在or组合中列出所有可能的命令,似乎更优雅的做法是使用符号表。
现在我开始得很简单(假设我只有两个可能的命令,不需要消耗任何参数),但我已经陷入困境。
我读到了nabialek技巧,它也在boost示例中列出,我尝试了以下代码:
#include <boost/spirit/home/qi/nonterminal/rule.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename Tag>
struct GenericCommand
{};
namespace tag {
struct none
{};
struct stop
{};
struct limit
{};
} // namespace tag
using None = GenericCommand<tag::none>;
using Stop = GenericCommand<tag::stop>;
using Limit = GenericCommand<tag::limit>;
using Command = std::variant<None, Stop, Limit>;
struct Grammar :
qi::grammar<std::string::const_iterator, Command (), qi::ascii::space_type>
{
using Iterator = std::string::const_iterator;
using Skipper = qi::ascii::space_type;
Grammar ();
using Rule = qi::rule<Iterator, Command (), Skipper>;
qi::symbols<char, const Rule*> commands;
qi::rule<Iterator, Command (), Skipper> command;
qi::rule<Iterator, Stop (), Skipper> stop_;
qi::rule<Iterator, Limit (), Skipper> limit_;
Rule parse, stop, limit, rest;
struct SetRest
{
explicit SetRest (Rule& rule) : rule {rule} {}
void operator() (Rule* real_rule) const { rule = *real_rule; }
Rule& rule;
};
};
Grammar::Grammar () : Grammar::base_type {parse}
{
using namespace qi;
parse = command;
commands.add ("stop", &stop) ("limit", &limit);
command = no_case[commands[SetRest {rest}]] >> rest;
stop_ = eps;
limit_ = eps;
stop = stop_;
limit = limit_;
}
这段代码给我带来了编译错误("no matching function for call to 'do_call'"),我不知道如何解释。为什么不起作用?我没有看到示例和我的代码之间的概念上的区别。还是说这个已经不起作用了?这个示例来自一个较旧的版本。
英文:
I want to parse command line arguments with boost::spirit. Instead of listing all possible commands in an or combination it seems more elegant to use a symbol table.
Now I started very simple (lets assume I only have 2 possible commands that do not consume any arguments) and I am already stuck.
I read about the nabialek trick that is also listed in the boost examples and I tried:
#include <boost/spirit/home/qi/nonterminal/rule.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template <typename Tag>
struct GenericCommand
{};
namespace tag {
struct none
{};
struct stop
{};
struct limit
{};
} // namespace tag
using None = GenericCommand<tag::none>;
using Stop = GenericCommand<tag::stop>;
using Limit = GenericCommand<tag::limit>;
using Command = std::variant<None, Stop, Limit>;
struct Grammar :
qi::grammar<std::string::const_iterator, Command (), qi::ascii::space_type>
{
using Iterator = std::string::const_iterator;
using Skipper = qi::ascii::space_type;
Grammar ();
using Rule = qi::rule<Iterator, Command (), Skipper>;
qi::symbols<char, const Rule*> commands;
qi::rule<Iterator, Command (), Skipper> command;
qi::rule<Iterator, Stop (), Skipper> stop_;
qi::rule<Iterator, Limit (), Skipper> limit_;
Rule parse, stop, limit, rest;
struct SetRest
{
explicit SetRest (Rule& rule) : rule {rule} {}
void operator() (Rule* real_rule) const { rule = *real_rule; }
Rule& rule;
};
};
Grammar::Grammar () : Grammar::base_type {parse}
{
using namespace qi;
parse = command;
commands.add ("stop", &stop) ("limit", &limit);
command = no_case[commands[SetRest {rest}]] >> rest;
stop_ = eps;
limit_ = eps;
stop = stop_;
limit = limit_;
}
This code gives me compile errors («no matching function for call to 'do_call'») I have no clue how to interpret. Why does this not work? I don't see a conceptual difference between the example and my code. Or is it that this stopped working? The example is from an older version.
答案1
得分: 1
感谢Marek,我发现我可以使用惰性解析器来跟踪符号,该解析器使用符号的属性。而且我忘记包含boost/phoenix/operator.hpp
。所以我的命令规则现在看起来像这样:
command = no_case[commands[_a = _1]] >> lazy(*_a)[_val = _1];
这个代码按预期工作。
展示这个示例的例子可以在boost.org网站上找到。
英文:
Thanks to Marek I found out that I can follow the symbols with the lazy parser that uses the attribute of the symbol. And I missed to include boost/phoenix/operator.hpp
. So my command rule now looks like this:
command = no_case[commands[_a = _1]] >> lazy(*_a)[_val = _1];
This works as expected.
The example showing this can be found on the boost.org Website.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论