iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++BoostSpirit入门教程
  • 701
分享到

C++BoostSpirit入门教程

C++BoostSpiritC++Spirit 2022-11-16 00:11:29 701人浏览 薄情痞子
摘要

目录一、Boost.Spirit库介绍二、boost::spirit::qi::parse()解析格式三、解析器一、Boost.Spirit库介绍 本章介绍库 Boost.Spiri

一、Boost.Spirit库介绍

本章介绍库 Boost.Spirit。 Boost.Spirit 用于开发文本格式的解析器。例如,您可以使用 Boost.Spirit 开发解析器来加载配置文件。 Boost.Spirit 也可以用于二进制格式,尽管它在这方面的用处有限。

Boost.Spirit 简化了解析器的开发,因为格式是用规则描述的。规则定义格式的外观——其余的由 Boost.Spirit 完成。您可以将 Boost.Spirit 与正则表达式进行比较,因为它可以让您处理复杂的过程——正则表达式的模式搜索和 Boost.Spirit 的解析——而无需编写代码来实现该过程。

Boost.Spirit 期望使用解析表达式语法 (PEG) 来描述规则。 PEG 与扩展巴库斯-瑙尔形式 (EBNF) 有关。即使您不熟悉这些语言,本章中的示例也足以帮助您入门

Boost.Spirit 有两个版本。第一个版本称为 Spirit.Classic。这个版本不应该再使用了。当前版本是 2.5.2。这是本章介绍的版本。

从 2.x 版本开始,Boost.Spirit 可用于生成生成器和解析器。解析器读取文本格式,生成器编写它们。 Boost.Spirit 中用于开发解析器的组件称为 Spirit.Qi。 Spirit.Karma 是用于开发生成器的组件。命名空间被相应地划分:用于开发解析器的类和函数可以在 boost::spirit::qi 中找到,用于开发生成器的类和函数可以在 boost::spirit::karma 中找到。

除了 Spirit.Qi 和 Spirit.Karma,该库还包含一个名为 Spirit.Lex 的组件,可用于开发词法分析器。

本章的重点是开发解析器。示例主要使用来自 boost::spirit 和 boost::spirit::qi 的类和函数。对于这些类和函数,包含头文件 boost/spirit/include/qi.hpp 就足够了。

如果您不想包含像 boost/spirit/include/qi.hpp 这样的主头文件,您可以单独包含来自 boost/spirit/include/ 的头文件。仅包含此目录中的头文件很重要。 boost/spirit/include/ 是用户界面。其他目录中的头文件可以在新的库版本中更改。

二、boost::spirit::qi::parse()解析格式

Boost.Spirit 提供 boost::spirit::qi::parse() 和 boost::spirit::qi::phrase_parse() 来解析格式。

Example11.1.Usingboost::spirit::qi::parse()

#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::parse(it, s.end(), ascii::digit);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

例 11.1 引入了 boost::spirit::qi::parse()。这个函数需要两个被解析字符串的迭代器和一个解析器。该示例使用由 Boost.Spirit 提供的解析器 boost::spirit::ascii::digit。这是几个字符分类解析器之一。这些解析器测试字符是否属于某个类。 boost::spirit::ascii::digit 测试字符是否为 0 到 9 之间的数字。

该示例传递从 std::cin 读取的字符串的迭代器。请注意,开始迭代器没有直接传递给 boost::spirit::qi::parse()。它存储在变量 it 中,然后传递给 boost::spirit::qi::parse()。这样做是因为 boost::spirit::qi::parse() 可能会修改迭代器。

如果您键入一个数字,然后按 Enter,该示例将显示 true。如果您输入两位数然后回车,则输出将为真,后跟第二位数字。如果你输入一个字母然后回车,输出将是假的,然后是字母。

例 11.1 中使用的解析器 boost::spirit::ascii::digit 只测试一个字符以查看它是否是数字。如果第一个字符是数字,boost::spirit::qi::parse() 返回 true,否则返回 false。 boost::spirit::qi::parse() 的返回值表示解析器是否成功。

boost::spirit::qi::parse() 如果您输入多个数字,也会返回 true。因为解析器 boost::spirit::ascii::digit 只测试第一个字符,所以它会在这样的字符串上成功。第一个之后的所有数字都将被忽略。

为了让您确定可以成功解析多少字符串,boost::spirit::qi::parse() 更改了它的迭代器。调用 boost::spirit::qi::parse() 后,它指向最后一个解析成功后的字符。如果输入多个数字,则指第二个数字。如果您只输入一位数字,则它等于 s 的结束迭代器。如果你输入一个字母,它指的是那个字母。

boost::spirit::qi::parse() 不会忽略空格。如果运行示例 11.1 并输入空格,则会显示 false。 boost::spirit::qi::parse() 测试第一个输入的字符,即使该字符是空格。如果你想忽略空格,使用 boost::spirit::qi::phrase_parse() 而不是 boost::spirit::qi::parse()。

Example11.2.Usingboost::spirit::qi::phrase_parse()

#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(), ascii::digit, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

boost::spirit::qi::phrase_parse() 的工作方式与 boost::spirit::qi::parse() 类似,但需要另一个名为 skipper 的参数。船长是应该被忽略的字符的解析器。示例 11.2 使用 boost::spirit::ascii::space,一个字符分类解析器来检测空格,作为船长。

boost::spirit::ascii::space 丢弃空格作为分隔符。如果您开始该示例并输入一个空格后跟一个数字,则显示为 true。与前面的示例不同,解析器 boost::spirit::ascii::digit 不应用于空格,而是应用于不是空格的第一个字符。

请注意,此示例忽略了任意数量的空格。因此,如果您输入多个空格后跟一个数字, boost::spirit::qi::phrase_parse() 将返回 true。

与 boost::spirit::qi::parse() 一样,boost::spirit::qi::phrase_parse() 修改了作为第一个参数传递的迭代器。这样,您就知道解析器能够成功工作到字符串多远。示例 11.2 跳过成功解析字符后出现的空格。如果您输入一个数字后跟一个空格,然后是一个字母,迭代器将引用该字母,而不是它前面的空格。如果您希望迭代器引用空间,请将 boost::spirit::qi::skip_flag::dont_postskip 作为另一个参数传递给 boost::spirit::qi::phrase_parse()。

Example11.3.phrase_parse()withboost::spirit::qi::skip_flag::dont_postskip

#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(), ascii::digit, ascii::space,
    qi::skip_flag::dont_postskip);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.3 将 boost::spirit::qi::skip_flag::dont_postskip 传递给 boost::spirit::qi::phrase_parse() 以告诉解析器不要跳过在成功解析数字之后但在第一个不成功数字之前出现的空格解析的字符。如果你输入一个数字后跟一个空格再跟一个字母,它指的是调用 boost::spirit::qi::phrase_parse() 之后的空格。

标志 boost::spirit::qi::skip_flag::postskip 是默认值,如果 boost::spirit::qi::skip_flag::dont_postskip 和 boost::spirit::qi::skip_flag 都不是,则使用该标志: :postskip 已指定。

Example11.4.boost::spirit::qi::phrase_parse()with wide strings

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
int main()
{
  std::wstring s;
  std::getline(std::wcin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space,
    qi::skip_flag::dont_postskip);
  std::wcout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::wcout << std::wstring{it, s.end()} << '\n';
}

boost::spirit::qi::parse() 和 boost::spirit::qi::phrase_parse() 接受迭代器到一个宽字符串。示例 11.4 与前面的示例类似,只是使用了宽字符串。

Boost.Spirit 还支持来自 c++11 标准库的字符串类型 std::u16string 和 std::u32string。

三、解析器

本节说明如何定义解析器。您通常从 Boost.Spirit 访问现有的解析器——例如 boost::spirit::ascii::digit 或 boost::spirit::ascii::space。通过组合解析器,您可以解析更复杂的格式。该过程类似于定义正则表达式,它们也是由基本构建块构建的。

Example11.5.A parser for two consecutive digits

#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(), ascii::digit >> ascii::digit,
    ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.5 测试是否输入了两个数字。 boost::spirit::qi::phrase_parse() 仅在两个数字连续时才返回 true。空格被忽略。

与前面的示例一样, boost::spirit::ascii::digit 用于识别数字。因为 boost::spirit::ascii::digit 只测试一个字符,所以解析器使用了两次来测试两位数字的输入。要连续两次使用 boost::spirit::ascii::digit,必须使用运算符。 Boost.Spirit 为解析器重载 operator>>。使用 ascii::digit >> ascii::digit 创建了一个解析器,用于测试字符串是否包含两个数字。

如果您运行该示例并输入两位数,则会显示 true。如果您只输入一位数字,该示例将显示为 false。

请注意,如果您在两位数之间输入空格,该示例也会显示 true。无论在解析器中使用运算符 operator>> 的任何位置,都允许使用被船长忽略的字符。因为示例 11.5 使用 boost::spirit::ascii::space 作为跳过符,所以您可以在两个数字之间输入任意数量的空格。

如果您希望解析器仅在两个数字之间没有空格的情况下才接受它们,请使用 boost::spirit::qi::parse() 或指令 boost::spirit::qi::lexeme。

Example11.6.Parsing character by character withboost::spirit::qi::lexeme

#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::lexeme[ascii::digit >> ascii::digit], ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.6 使用解析器 qi::lexeme[ascii::digit >> ascii::digit]。现在, boost::spirit::qi::phrase_parse() 仅在数字之间没有空格时才返回 true。

boost::spirit::qi::lexeme 是可以改变解析器行为的几个指令之一。如果你想禁止在使用 operator>> 时会被船长忽略的字符,你可以使用 boost::spirit::qi::lexeme。

Example11.7.Boost.Spirit rules similar to regular expressions

#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(), +ascii::digit, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

例 11.7 用 +ascii::digit 定义了一个解析器,它至少需要一个数字。这种语法,特别是加号 (+),类似于正则表达式中使用的语法。加号标识一个字符或字符组,该字符或字符组预计在字符串中至少出现一次。如果您启动示例并输入至少一位数字,则会显示 true。数字是否由空格分隔并不重要。如果解析器应该只接受没有空格的数字,请再次使用 boost::spirit::qi::lexeme。

Example11.8.Numeric 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_, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

示例 11.8 需要一个整数。 boost::spirit::qi::int_ 是一个可以识别正整数和负整数的数值解析器。与 boost::spirit::ascii::digit 不同,boost::spirit::qi::int_ 可以将多个字符(例如 +1 或 -23)识别为整数。

Boost.Spirit 提供了额外的逻辑解析器。 boost::spirit::qi::float_、boost::spirit::qi::double_ 和 boost::spirit::qi::bool_ 是可以读取浮点数和布尔值的数值解析器。使用 boost::spirit::qi::eol,您可以测试行尾字符。 boost::spirit::qi::byte_ 和 boost::spirit::qi::Word 可用于读取一个或两个字节。 boost::spirit::qi::word 和其他二进制解析器识别平台的字节顺序并进行相应的解析。如果要基于特定的字节序进行解析,无论平台如何,都可以使用 boost::spirit::qi::little_word 和 boost::spirit::qi::big_word 等解析器。

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

--结束END--

本文标题: C++BoostSpirit入门教程

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

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

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

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

下载Word文档
猜你喜欢
  • C++BoostSpirit入门教程
    目录一、Boost.Spirit库介绍二、boost::spirit::qi::parse()解析格式三、解析器一、Boost.Spirit库介绍 本章介绍库 Boost.Spiri...
    99+
    2022-11-16
    C++ Boost Spirit C++ Spirit
  • C#中Linq的入门教程
    一、LINQ的体系结构 语言集成查询 (LINQ) (C#) | Microsoft 官方文档 LINQ总共包括五个部分:  程序集命名空间描述LINQ to Object...
    99+
    2024-04-02
  • C++教程(超长最全入门)
    目录1、C++简介1.1 起源1.2 应用范围1.3 C++和C2、开发工具3、基本语法3.1 注释3.2关键字3.3标识符4、数据类型4.1基本数据类型4.2 数据类型在不同系统中...
    99+
    2023-05-18
    C++教程
  • Python爬虫入门教程 1-100 C
    简介 你好,当你打开这个文档的时候,我知道,你想要的是什么! Python爬虫,如何快速的学会Python爬虫,是你最期待的事情,可是这个事情应该没有想象中的那么容易,况且你的编程底子还不一定好,这套课程,没有你想要的Python基础,没...
    99+
    2023-01-30
    爬虫 入门教程 Python
  • Jmeter入门教程
    目录一、下载二、安装三、运行四、一个简单的压测实例五、如何查看系统负载何性能瓶颈jemter简介 jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全...
    99+
    2024-04-02
  • ECharts入门教程
    Echart 官网:https://echarts.apache.org/zh/index.html下载页面:https://echarts.apache.org/zh/downlo...
    99+
    2024-04-02
  • Navicat入门教程
    本篇内容主要讲解“Navicat入门教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Navicat入门教程”吧!一、 连接使用 1.1 连接数据库打...
    99+
    2024-04-02
  • HTML5 入门教程
    本篇内容主要讲解“HTML5 入门教程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“HTML5 入门教程”吧!JavaScript作为一种弱类型语言,最大的特点就是动态类型。也就是说不用提前声明...
    99+
    2023-06-09
  • maven3 入门教程
    Maven库: http://repo2.maven.org/maven2/ Maven依赖查询: http://mvnrepository.com/ Maven常用命令:  1. 创建Maven的普通java项目:  ...
    99+
    2023-01-31
    入门教程
  • Lighttpd入门教程
    Lighttpd入门教程 概述入门教程安装配置静态文件服务动态文件服务 虚拟主机SSL启动服务器日志模块总结lighthttpd使用场景和原理使用场景原理 概述 Lightt...
    99+
    2023-09-04
    服务器 linux ubuntu
  • Flask 入门教程
    Flask 入门教程 一、Flask简单使用 1、准备环境 硬件:Windows 7+python 3.6+安装软件:pycharm安装(社区版)、python环境安装 2、简单的Flask应用 本地...
    99+
    2023-10-07
    flask python 后端
  • ECMAScript6入门教程
    目录你的浏览器支持ES吗?ES 6 新特性汇总(一图全览)1. let、const 和 block 作用域2. 箭头函数(Arrow Functions)3. 函数参数默认值4. S...
    99+
    2024-04-02
  • IPv6入门教程
    本篇文章主要从基础概念、IPv6的相关网络工具、关于移动应用在IPv6和IPv4网络环境中自动降级机制的研究等三个方面介绍了IPv6的入门教程。前言众所周知,32位的IPv4地址已经基本耗尽(这里的耗尽只是说的分配完了,实际上有相当一部分并...
    99+
    2023-06-03
  • Python入门教程(二)
      今天讲编程思维。  可能这对初次接触编程的人有用——我不是不想切入正题,我只是想强调根本没什么正题,我可能在其他文章里提过这一点。“编程语言就是语法糖”,可能你不知道什么是语法糖,但是知道的人也未必认同我。我不保证你们能听懂……pyth...
    99+
    2023-01-31
    入门教程 Python
  • Python Qt5 入门教程
    Python Qt5 入门教程 Python Qt5是一个强大的GUI工具包,可以用来设计各种桌面应用程序,包括图形用户界面、数据库应用程序等。本教程将带你入门Python Qt5,从安装开始到图形界面的设计以及常见的控件和事件。 安装...
    99+
    2023-08-31
    python ubuntu linux Qt5
  • Python NLP 入门教程
    本文简要介绍Python自然语言处理(NLP),使用Python的NLTK库。NLTK是Python的自然语言处理工具包,在NLP领域中,最常使用的一个Python库。什么是NLP?简单来说,自然语言处理(NLP)就是开发能够理解人类语言的...
    99+
    2023-01-31
    入门教程 Python NLP
  • python入门教程(一)
      我们依然不讲代码,而是先说命令行。   为什么命令行如此重要?之前说到,命令行是你和电脑对话的地方。你可以用句子的方式把信息发给电脑,电脑再以句子的方式给你回应。在编程领域,有些消息只能用命令行告诉电脑——或许是编程人员早就习惯了,或许...
    99+
    2023-01-31
    入门教程 python
  • python入门教程(零)
    (本文针对Windows)   Python是什么?是一种编程语言。编程语言是什么?就是和机器说话的方式。编译器和解释器好比翻译,把你的话翻成机器听得懂的。但是这些翻译不怎么智能(虽然也有高下),你必须说一套很机械的官腔,他们才帮你翻译——...
    99+
    2023-01-31
    入门教程 python
  • linux入门教程(3)
    (文:flynng)  3.4 进程管理  Linux是一个多用户多任务的操作系统。多用户是指多个用户可以在同一时间使用计算机系统;多任务是指Linux可以同时执行几个任务,它可以在还未执行完一个任务时又执行另一项任务。  在Linux系统...
    99+
    2023-01-31
    入门教程 linux
  • Spring Batch入门教程篇
    SpringBatch介绍:SpringBatch 是一个大数据量的并行处理框架。通常用于数据的离线迁移,和数据处理,⽀持事务、并发、流程、监控、纵向和横向扩展,提供统⼀的接⼝管理和任务管理;Spr...
    99+
    2023-05-31
    springbatch 入门 tc
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作