Boost Spirit Qi符号默认值和NULL值
Boost Spirit Qi Symbols default value and NULL value
Boost Spirit qi::symbols实现了键值对的映射:给出一个字符串的键值,就可以返回某个值。我的问题是:
1)对于空白字符串,是否可以返回默认值?(代码中Q1)
2)对于非空字符串或键-值对映射中列出的键的字符串,是否可能返回一个值表示该键无效?(代码中Q2)
**以下代码基于BOOST SPIRIT文档。**事先感谢您的建议。
#include <boost/spirit/include/support_utree.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/assert.hpp>
#include <iostream>
#include <string>
#include <cstdlib>
template <typename P, typename T>
void test_parser_attr(
char const* input, P const& p, T& attr, bool full_match = true)
{
using boost::spirit::qi::parse;
char const* f(input);
char const* l(f + strlen(f));
if (parse(f, l, p, attr) && (!full_match || (f == l)))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
int main()
{
using boost::spirit::qi::symbols;
symbols<char, int> sym;
sym.add
("Apple", 1)
("Banana", 2)
("Orange", 3)
;
int i;
test_parser_attr("Banana", sym, i);
std::cout << i << std::endl; // 2
test_parser_attr("", sym, i); // Q1: key is "",
std::cout << i << std::endl; // would like it to be 1 as default
test_parser_attr("XXXX", sym, i); // Q2: key is other than "Apple"/"Banana"/"Orange",
std::cout << i << std::endl; // would like it to be 4
return 0;
}
您不能仅仅使用qi::symbols
来完成您想要的。应该有可能创建一个达到预期结果的Spirit终端/指令,但这样做会非常复杂,并且需要了解qi::symbols
和相关类的内部工作原理,所以我认为这不是一个值得的方法。幸运的是,使用qi::attr(val)
有一个非常简单的替代方案,一个不消耗任何输入的解析器,将val
暴露为其属性并且总是成功。
让我们看看这三种情况:
- 如果字符串在符号表中,则返回其关联值
->
,仅使用sym
- 如果字符串为空返回1
->
只使用attr(1)
- 如果字符串不在符号表中返回4
->
,则需要使用attr(4)
,但这还不够,因为您还需要消耗字符串。如果我们假设字符串只由字母组成,omit[+alpha]
可以工作(omit
丢弃文本,+
确保至少有一个字母)。
您需要将这三个解析器放在另一个解析器中,记住在每种情况下实际使用的解析器将是第一个成功的解析器:
sym | omit[+alpha] >> attr(4) | attr(1)
可能的问题:
- 如果你的非符号表字符串可以更复杂,你需要适当地改变
+alpha
。 - 如果你正在使用一个船长,你可能需要使用
omit[
lexeme
[+alpha]]
来停止贪婪的+
。
完整样本(在WandBox上运行)
#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>
template <typename P, typename T>
void test_parser_attr(
char const* input, P const& p, T& attr, bool full_match = true)
{
using boost::spirit::qi::parse;
char const* f(input);
char const* l(f + strlen(f));
if (parse(f, l, p, attr) && (!full_match || (f == l)))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
int main()
{
using boost::spirit::qi::symbols;
symbols<char, int> sym;
sym.add
("Apple", 1)
("Banana", 2)
("Orange", 3)
;
using boost::spirit::qi::attr;
using boost::spirit::qi::alpha;
using boost::spirit::qi::omit;
using boost::spirit::qi::lexeme;
//if the text is in the symbol table return the associated value
//else if the text is formed by letters (you could change this using for example `alnum`) and contains at least one, discard the text and return 4
//else return 1
boost::spirit::qi::rule<char const*,int()> symbols_with_defaults = sym | omit[+alpha] >> attr (4) | attr(1);
int i;
test_parser_attr("Banana", symbols_with_defaults, i);
std::cout << i << std::endl; // 2
test_parser_attr("", symbols_with_defaults, i); // Q1: key is "",
std::cout << i << std::endl; // would like it to be 1 as default
test_parser_attr("XXXX", symbols_with_defaults, i); // Q2: key is other than "Apple"/"Banana"/"Orange",
std::cout << i << std::endl; // would like it to be 4
std::vector<int> values;
test_parser_attr("<Banana>,<>,<xxxx>", ('<' >> symbols_with_defaults >> '>')%',', values);
for(int val : values)
std::cout << val << " "; // should be '2 1 4'
std::cout << std::endl;
return 0;
}
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 具有默认值的引用获取函数
- 当给定默认值时,为什么此模板参数推导失败
- 从具有默认值的部分指定模板类继承时发生SWIG错误,具有不带默认值的正向声明
- 格式化浮点值:返回默认值
- 如何将数组部分初始化为某个默认值?
- asn1c 不会从 asn.1 模块中提取八位字节字符串的默认值
- 创建一个包含 c++ 默认值的环境文件
- C++(和 ROS) - 包含与前向声明引用,设置默认值和类型定义
- Makefile g++ 使用命令行中的 -D 变量进行编译,默认值
- Switch 语句(字符串)一直选择默认值,除非其为零
- 如何使用默认值将枚举声明为 extern
- 如何在提升程序选项中设置矢量<矢量>的默认值<string>
- 如何使用默认值为构造函数中的枚举赋值?
- 变量始终在函数中重置为默认值
- 如何在C++中提供模板化函数作为另一个函数的参数,默认值?
- 函数不返回默认值
- 具有公共范围与专用范围的默认值的C++的不同行为
- 从指针访问值或获取其默认值(如果为 null)的最干净方法
- Boost Spirit Qi符号默认值和NULL值