广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++ Boost Spirit进阶教程
  • 134
分享到

C++ Boost Spirit进阶教程

C++ Boost SpiritC++ Spirit介绍 2022-11-16 00:11:28 134人浏览 泡泡鱼
摘要

目录一、行动二、属性一、行动 到目前为止,本章中的示例只检测到两件事:解析器是否成功以及解析器在哪里结束。但是,解析器通常以某种方式处理数据,正如您将在下一个示例中看到的那样。 Ex

一、行动

到目前为止,本章中的示例只检测到两件事:解析器是否成功以及解析器在哪里结束。但是,解析器通常以某种方式处理数据,正如您将在下一个示例中看到的那样。

Example11.9.Linking actions with parsers

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iOStream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(),
    qi::int_[([](int i){ std::cout << i << '\n'; })], ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.9 使用 boost::spirit::qi::int_ 解析一个整数,然后将该整数写入标准输出。这就是为什么一个动作与 boost::spirit::qi::int_ 相关联。动作是应用解析器时调用的函数或函数对象。链接是使用运算符 operator[] 完成的,它被 boost::spirit::qi::int_ 和其他解析器重载。示例 11.9 使用 lambda 函数作为操作,该操作需要一个 int 类型的唯一参数并将其写入标准输出。

如果您启动示例 11.9 并输入一个数字,则会显示该数字。

传递给动作的参数类型取决于解析器。例如, boost::spirit::qi::int_ 转发一个 int 值,而 boost::spirit::qi::float_ 传递一个 float 值。

Example11.10.Boost.Spirit with Boost.Phoenix

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix/phoenix.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
using boost::phoenix::ref;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  int i;
  bool match = qi::phrase_parse(it, s.end(), qi::int_[ref(i) = qi::_1],
    ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (match)
    std::cout << i << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.10 使用 Boost.Phoenix 将使用 boost::spirit::qi::int_ 解析的 int 值存储在 i 中。如果 boost::spirit::qi::phrase_parse() 返回 true,则将 i 写入标准输出。

这个例子在包含来自 Boost.Spirit 的头文件之前定义了宏 BOOST_SPIRIT_USE_PHOENIX_V3。此宏选择 Boost.Phoenix 的第三个和当前版本。这很重要,因为 Boost.Phoenix 是从 Boost.Spirit 派生的,而 Boost.Spirit 包含 Boost.Phoenix 的第二个版本。如果未定义 BOOST_SPIRIT_USE_PHOENIX_V3,则 Boost.Phoenix 的第二个版本将包含在 Boost.Spirit 头文件中,第三个版本将包含在 boost/phoenix/phoenix.hpp 中。不同的版本会导致编译器错误。

请注意如何详细定义 lambda 函数。 boost::phoenix::ref() 创建对变量 i 的引用。但是,占位符 _1 不是来自 Boost.Phoenix,而是来自 Boost.Spirit。这很重要,因为 boost::spirit::qi::_1 提供了对具有通常预期类型的​​解析值的访问——示例 11.10 中的 int。如果 lambda 函数使用 boost::phoenix::placeholders::arg1,编译器会报错,因为 boost::phoenix::placeholders::arg1 不代表 int;它将基于 Boost.Spirit 中的另一种类型,并且需要提取 int 值。

二、属性

操作是处理解析值的一种选择。另一种选择是将对象传递给 boost::spirit::qi::parse() 或 boost::spirit::qi::phrase_parse() 用于存储解析值。这些对象称为属性。它们的类型必须与解析器的类型相匹配。

您已经在上一节中使用过属性。传递给动作的参数也是属性。每个解析器都有一个属性。例如,解析器 boost::spirit::qi::int_ 具有 int 类型的属性。在以下示例中,属性不会作为参数传递给函数。相反,解析后的值存储在属性中,可以在 boost::spirit::qi::parse() 或 boost::spirit::qi::phrase_parse() 返回后处理。

Example11.11.Storing anintvalue in an attribute

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  int i;
  if (qi::phrase_parse(it, s.end(), qi::int_, ascii::space, i))
    std::cout << i << '\n';
}

示例 11.11 使用解析器 boost::spirit::qi::int_。解析后的 int 值存储在变量 i 中。 i 作为另一个参数传递给 boost::spirit::qi::phrase_parse(),因此成为解析器 boost::spirit::qi::int_ 的一个属性。 如果您启动示例 11.11 并输入一个数字,该数字将被写入标准输出流。

Example11.12.Storing severalintvalues in an attribute

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <vector>
#include <iterator>
#include <alGorithm>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  std::vector<int> v;
  if (qi::phrase_parse(it, s.end(), qi::int_ % ',', ascii::space, v))
  {
    std::ostream_iterator<int> out{std::cout, ";"};
    std::copy(v.begin(), v.end(), out);
  }
}

示例 11.12 使用了一个用 qi::int_ % ',' 定义的解析器。解析器接受由逗号分隔的任意数量的整数。像往常一样忽略空格。

因为解析器可以返回多个 int 值,所以属性的类型必须支持存储多个 int 值。该示例传递一个向量。如果您开始该示例并输入多个以逗号分隔的整数,则这些整数将写入以分号分隔的标准输出流。

除了向量,您还可以传递其他类型的容器,例如 std::list。Boost.Spirit 文档描述了哪些属性类型必须与哪些运算符一起使用。

到此这篇关于c++ Boost Spirit进阶教程的文章就介绍到这了,更多相关C++ Boost Spirit内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++ Boost Spirit进阶教程

本文链接: https://www.lsjlt.com/news/173074.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ Boost Spirit进阶教程
    目录一、行动二、属性一、行动 到目前为止,本章中的示例只检测到两件事:解析器是否成功以及解析器在哪里结束。但是,解析器通常以某种方式处理数据,正如您将在下一个示例中看到的那样。 Ex...
    99+
    2022-11-16
    C++ Boost Spirit C++ Spirit介绍
  • C++ Boost Spirit精通教程
    目录rule规则语法练习rule规则 在 Boost.Spirit 中,解析器由规则组成。由于规则通常基于 Boost.Spirit 提供的解析器,因此没有明显的区别。例如, boo...
    99+
    2022-11-16
    C++ Boost Spirit C++ Spirit介绍
  • C语言进阶教程之预处理
    目录一.代码运行是的两种环境二.翻译环境三.预定义符号四.#define1.define  定义宏2.带有副作用的宏参数五.#define定义宏 与函数对比六.预处理指令七...
    99+
    2023-02-10
    什么是预处理 c语言编译预处理命令 c语言预处理指令作用
  • C语言进阶栈帧示例详解教程
    目录正片开始栈有什么用?寄存器main函数创建局部变量创建函数部分形参与实参正片开始 今天来讲讲我对栈帧创建与销毁的拙见。理解什么是栈帧首先知道什么是栈: 在数据结构中, 栈是限定仅...
    99+
    2022-11-13
  • C语言进阶教程之函数指针详解
    目录一、函数指针1.概念1.2函数指针的使用方法1.3练习巩固1.4小结一下二、阅读两段有趣的代码1.( *(void( *)( ))0 )( )2.void (* signal(i...
    99+
    2022-11-13
  • C语言进阶教程之字符串&内存函数
    目录前言:一、求字符串长度strlenstrlen函数的模拟实现二、长度不受限制的字符串函数strcpystrcpy函数的模拟实现strcatstrcat函数的模拟实现strcmps...
    99+
    2022-11-12
  • C++初阶教程之类和对象
    目录类和对象<上>1. 类的定义2. 类的封装2.1 访问限定修饰符2.2 类的封装3. 类的使用3.1 类的作用域3.2 类的实例化4. 类对象的存储5. this 指...
    99+
    2022-11-13
  • 【MySQL进阶教程】SQL优化
    前言 本文为 【MySQL进阶教程】SQL优化 相关知识,下边将对主键优化,order by优化,group by优化,limit优化,count优化,update优化等进行详尽介绍~ &...
    99+
    2023-09-21
    mysql sql 数据库
  • 【MySQL进阶教程】MySQL管理
    前言 本文为 【MySQL进阶教程】MySQL管理 相关知识,下边将对系统数据库,常用工具(包括:mysql、mysqladmin、mysqlbinlog、mysqlshow、mysqldump、mysqlimport/source)等进...
    99+
    2023-08-16
    mysql 数据库 服务器
  • 【MySQL进阶教程】InnoDB引擎
    前言 本文为 【MySQL进阶教程】InnoDB引擎 相关知识,下边将对InnoDB引擎介绍,InnoDB引擎架构,事务原理,MVCC等进行详尽介绍~ 📌博主主页:小新要变强 的主页...
    99+
    2023-09-13
    mysql 数据库 java
  • C语言进阶教程之循环语句缺陷详析
    目录前言1 循环语句的三要素2 使用不同循环语句实现六种排列组合2.1 第一种排列(ABC)2.2 第二种排列(ACB)2.3 第三种排列(BCA)2.4 第四种排列(CBA)2.5...
    99+
    2022-11-12
  • C语言进阶教程之字符函数&字符串函数
    目录1、strlen1.1、三种模拟实现2、长度不受限制的字符串函数2.1、strcpy2.1.1、模拟实现2.2、strcat2.2.1、模拟实现2.3、strcmp2.3.1、模...
    99+
    2022-11-13
  • React中的Hooks进阶理解教程
    目录Hooks进阶useState - 回调函数的参数useEffect - 清理副作用useEffect - 发送网络请求useRefuseContextHooks进阶 useSt...
    99+
    2022-11-13
  • Go gRPC进阶教程gRPC转换HTTP
    目录前言gRPC转成HTTP编写和编译proto服务端代码修改使用postman测试生成swagger文档把swagger-ui转成Go代码,备用对外提供swagger-ui在swa...
    99+
    2022-11-13
  • (二)《SQL进阶教程》学习记录-
    GROUP BY、PARTITION BY,分组取前几条,分组完整记录,排名、排序 (一) 《SQL进阶教程》学习记录--CASE (二) 《SQL进阶教程》学习记录--GROUP BY、PA...
    99+
    2016-09-20
    (二)《SQL进阶教程》学习记录-
  • Python入门进阶教程-JSON操作
    什么是JSON?JSON 的全称是 JavaScript Object Notation,即 JavaScript 对象符号,它是一种轻量级、跨平台、跨语言的数据交换格式,其设计意图是把所有事情都用设计的字符串来表示,这样既方便在互联网上传...
    99+
    2023-06-02
  • 【MySQL进阶教程】 索引详细介绍
    前言 本文为 【MySQL进阶教程】 索引 相关知识介绍,下边具体将对索引概述,索引结构(包括:索引结构概述,二叉树,B-Tree,B+Tree,Hash),索引分类,索引语法(包括:创建索引,查看...
    99+
    2023-10-03
    mysql java 数据库
  • Go gRPC服务进阶middleware使用教程
    目录前言go-grpc-middleware简介grpc_zap日志记录grpc_auth认证grpc_recovery恢复总结前言 之前介绍了gRPC中TLS认证和自定义方法认证,...
    99+
    2022-11-13
  • pytest进阶教程之fixture函数详解
    fixture函数存在意义   与python自带的unitest测试框架中的setup、teardown类似,pytest提供了fixture函数用以在测试执行前和执行后进行必要...
    99+
    2022-11-12
  • pandas进阶教程之Dataframe的apply方法
    目录apply方法介绍用例1用例2用例3总结 apply方法介绍 方法形式为 apply(func, axis=0, raw=False, result_type=None...
    99+
    2022-11-11
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作