gpt4 book ai didi

c++ - Boost::Spirit 中的复合语法

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:47:43 26 4
gpt4 key购买 nike

我有以下语法,它按预期工作。

struct query_term {
std::string term;
bool is_tag;

query_term(const std::string &a, bool tag = false): term(a), is_tag(tag) { } };

template<typename Iterator> struct query_grammar: grammar<Iterator, std::vector<query_term>(), space_type> {
query_grammar():
query_grammar::base_type(query) {

word %= +alnum;
tag = (omit[word >> ':'] >> word[_val = phoenix::construct<query_term>(_1, true)]);
non_tag = word[_val = phoenix::construct<query_term>(_1, false)];
query = (
(omit[word >> ':'] >> word[push_back(_val, phoenix::construct<query_term>(_1, true))])
|
word[push_back(_val,
phoenix::construct<query_term>(_1))
]
) % space;
};

qi::rule<Iterator, std::string(), space_type> word;
qi::rule<Iterator, query_term, space_type> tag;
qi::rule<Iterator, query_term, space_type> non_tag;
qi::rule<Iterator, std::vector<query_term>(), space_type> query; };

但是当我将查询替换为

query = (
tag[phoenix::push_back(_val, _1)]
|
word[push_back(_val,
phoenix::construct<query_term>(_1))
]
) % space;

代码无法编译。基本上我试图将语法拆分成可以在更大的语法中重用的组件。解析单词或标签时,在 tagword 规则中创建一个带有适当标志的 query_term 对象。在查询规则中重新使用这些属性。

在以前的版本中,标记和单词规则是内联在查询语法中的。

我不确定我在这里遗漏了什么。任何帮助将不胜感激。

仅供引用:这不是最终代码。在生产代码中使用它之前,我正在尝试这些规则。

谢谢,-- 巴利加

最佳答案

真正的问题是您将标记/非标记规则的属性定义为 query_term(而不是 query_term())。

一些小问题似乎是:

  • 使用 word 而不是 non_tag(公开一个不会转换为 query_type 的 std::string)
  • % space 与 space skipper 一起使用没有任何意义
  • 您可能希望在 word 规则中使用 lexeme,否则,无论空格如何,它都会继续“吃掉”字符

其他建议:

  • 避免使用命名空间 的范围过大(或完全避免)。您遇到难以发现或难以修复的冲突(例如 boost::cref 与 std::cref、std::string 与 qi::string 等)。

  • 尽量降低 Phoenix 的使用率。在这种情况下,我认为使用带有改编结构的 qi::attr 会容易得多。

  • 使用 BOOST_SPIRIT_DEBUG_* 宏深入了解您的解析器

这是我建议的完整语法:

template<typename Iterator> struct query_grammar: qi::grammar<Iterator, std::vector<query_term>(), qi::space_type>
{
query_grammar() : query_grammar::base_type(query)
{
using namespace qi;

word = lexeme[ +alnum ];

tag = omit[word >> ':'] >> word >> attr(true);

non_tag = word >> attr(false);

query = *(tag | non_tag);
};

qi::rule<Iterator, std::string() , qi::space_type> word;
qi::rule<Iterator, query_term() , qi::space_type> tag, non_tag;
qi::rule<Iterator, std::vector<query_term>(), qi::space_type> query;
};

一个完整的输出示例(简单地使用 karma 单行):

// #define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>

namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;

struct query_term {
std::string term;
bool is_tag;
};

BOOST_FUSION_ADAPT_STRUCT(query_term, (std::string,term)(bool,is_tag));

template<typename Iterator> struct query_grammar: qi::grammar<Iterator, std::vector<query_term>(), qi::space_type>
{
query_grammar() : query_grammar::base_type(query)
{
using namespace qi;

word = lexeme[ +alnum ];

tag = omit[word >> ':'] >> word >> attr(true);

non_tag = word >> attr(false);

query = *(tag | non_tag);

BOOST_SPIRIT_DEBUG_NODE(word);
BOOST_SPIRIT_DEBUG_NODE(tag);
BOOST_SPIRIT_DEBUG_NODE(non_tag);
BOOST_SPIRIT_DEBUG_NODE(query);
};

qi::rule<Iterator, std::string() , qi::space_type> word;
qi::rule<Iterator, query_term() , qi::space_type> tag, non_tag;
qi::rule<Iterator, std::vector<query_term>(), qi::space_type> query;
};


int main()
{
const std::string input = "apple tag:beer banana grape";
typedef std::string::const_iterator It;

query_grammar<It> parser;
std::vector<query_term> data;

It f(input.begin()), l(input.end());
bool ok = qi::phrase_parse(f, l, parser, qi::space, data);

if (ok)
std::cout << karma::format(karma::delimit [ karma::auto_ ] % karma::eol, data) << '\n';
if (f!=l)
std::cerr << "Unparsed: '" << std::string(f,l) << "'\n";

return ok? 0 : 255;
}

输出:

apple false 
beer true
banana false
grape false

关于c++ - Boost::Spirit 中的复合语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9850751/

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