Boost::Spirit中的复合语法
Composite grammar in Boost::Spirit
我有以下语法,可以按预期工作。
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;
代码无法编译。基本上,我试图将语法拆分为可以在更大的语法中重用的组件。解析单词或标记时,请在标记和单词规则中创建一个带有适当标志的query_term对象。在查询规则中重新使用这些属性。
在以前的版本中,标记和单词规则被内联在查询语法中。
我不确定我在这里错过了什么。如有任何帮助,我们将不胜感激。
仅供参考:这不是最终代码。在生产代码中使用这些规则之前,我正在试用这些规则。
Thanx,--巴利加
真正的问题是将标记/non_tag规则的属性定义为query_term
(而不是query_term()
)。
一些小问题似乎是:
- 使用
word
而不是non_tag
(公开一个不会转换为query_type
的std::字符串) - 与太空队长一起使用
% space
实际上没有意义 - 您可能希望
word
规则中包含lexeme
,因为否则,它将继续"吃掉"字符,而不考虑空白
其他建议:
-
避免CCD_ 9的过大范围(或完全避免)。您将遇到难以发现或难以修复的冲突(例如boost::cref与std::cre夫、std::string与qi::string等)。
-
尽量少用Phoenix。在这种情况下,我认为使用具有自适应结构的
qi::attr
会容易得多。 -
使用BOOstrongPIRIT_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;
};
一个完整的输出示例(使用因果报应进行琐碎的单线排列):
// #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
相关文章:
- 1d 智能指针不适用于语法 (*)++
- 助记符和指向成员语法的指针
- 有人能分解一下这个c++模板的语法吗
- C++避免重复声明的语法是什么
- QMetaObject invokeMethod的基于函数指针的语法
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 算术复合运算符重载为非成员
- 单独定义模板化嵌套类方法的正确语法
- C++模板函数中的初始化 - 新的初始值设定项表达式列表被视为复合表达式
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- 时间复杂度 当具有复合数据类型(如元组或对)时?
- HDF5Cpp 扩展复合数据集超板问题
- 为什么我会收到错误 C2143 语法错误:缺少"*"之前的';'?
- 奇怪的代码抛出编译错误模板< J,int aSize=10> C2143:语法错误:在"<"之前缺少";"
- 使用基类指针调用基类的值构造函数的语法是什么?
- 很好的语法来获取对向量/数组数据的大小引用?
- 使用复合语法解析时出现 Boost.spirit 分割错误
- Boost::Spirit中的复合语法